Java线程介绍

线程介绍

线程是程序运行的基本执行单元.

使用线程的优点:

  • 充分利用CPU资源。
  • 简化编程模型。
  • 简化异步事件的处理。
  • 节约成本。

线程的实现方式

Java中线程的实现有三种方式,分别是继承Thread类、实现Runnable接口和实现Callable接口。

  1. 继承Thread类

继承Thread类是Java中比较常见,也是很基础的一种实现Java多线程的方式。实现的方式也比较简单,只要将需要实现多线程的Java类继承java.lang.Thread类即可。该类中覆盖run()方法,将完成线程真正功能的代码写入run()方法中,然后调用Thread类中的start()方法启动线程。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
class MyThread extends Thread{

private String name;

public MyThread(String name){
this.name = name;
}

@Override
public void run() {
Thread.currentThread().setName(name);
System.out.println("I am Thread :" +name);
}

}


public class threadLearn {

public static void main(String[] args) {
//实例化继承了Thread的类
MyThread thread1 = new MyThread("Thread1");
//通过从Thread类中所继承的start()方法启动线程;
thread1.start();

}

}

  1. 实现Runnable接口

在Java中,类的继承是单一的,即一个子类仅可以继承一个父类,但可以实现多个接口。通过一个类继承Thread类来实现一个线程具有单继承的局限性,该子类不能再继承其他类,为了解决单继承的局限性,推荐通过实现Runnable()接口来实现一个线程。
使用Runnable()接口启动新线程的步骤如下:

(1)自定义类实现Runnable接口,并实现该接口的run()方法;

(2)用实现Runnable接口的对象作为参数实例化一个Thread对象;

(3)调用Thread类的start()方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class MyRunnable implements Runnable {
@Override
public void run() {
for (int i = 0;i < 10;i++) {
System.out.println("一边听歌");
}
}
}

public class Test {
public static void main(String[] args) {
new Thread(new MyRunnable()).start();
for (int i = 0;i < 10;i++) {
System.out.println("一边敲代码");
}
}
}
  1. 实现Callable接口

通过实现Callable接口,重写call()方法来实现一个线程。Callable接口是juc(java.util.concurrent)包下的一个泛型接口,只有一个call()方法。

Callable接口实现线程的步骤如下:

(1)自定义类实现Callable接口,并实现该接口的call()方法;
(2)创建实现Callable接口的自定义类对象;
(3)创建执行服务;
(4)提交执行;
(5)获取结果;
(6)关闭服务。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
class MyCallable implements Callable {

private String str;

public MyCallable(String str) {
this.str = str;
}

@Override
public Boolean call() throws Exception {
for (int i = 0;i < 10;i++) {
System.out.println("一边"+str);
}
return true;
}
}

public class Test {
public static void main(String[] args) throws InterruptedException, ExecutionException {
//创建目标对象
MyCallable mc1 = new MyCallable("唱歌");
MyCallable mc2 = new MyCallable("敲代码");
//创建执行服务
ExecutorService ser = Executors.newFixedThreadPool(2);
//提交执行
Future<Boolean> result1 = ser.submit(mc1);
Future<Boolean> result2 = ser.submit(mc2);
//获取结果
boolean r1 = result1.get();
boolean r2 = result2.get();
//关闭服务
ser.shutdownNow();

System.out.println("线程1执行结果:" + r1);//打印结果
System.out.println("线程2执行结果:" + r2);//打印结果
}
}

Callable接口与Runnable接口的功能类似,但提供了比Runnable更强大的功能,主要表现为以下三点:

  • Callable可以在任务结束后提供一个返回值,Runnable无法提供这个功能;

  • Callable接口中的call()方法可以抛出异常,而Runnable的run()方法不能抛出异常,必须在run()捕获;

  • 运行Callable可以拿到一个Future对象,Future对象表示异步计算的结果,它提供了检查计算是否完成的方法。由于线程属于异步计算模型,因此无法从别的线程中得到函数的返回值,在这种情况下,就可以使用Future来监视目标线程调用call()方法的情况,当调用Future的get方法以获取结果时,当前线程就会阻塞,直到call()方法结束返回结果。


Java线程介绍
http://www.wangxiaohuan.com/2020/02/26/2020-02-26/
作者
吃素的左撇子
发布于
2020年2月26日
许可协议