Java 的线程是程序执行中运算的最小单位,是程序调度运行的最基本的单位。
在 Java 中实现多线程操作有两种手段,一种是继承 Thread 类,另一种就是实现 Runnable 接口。
Thread 类是在 Java.lang
包中定义的一个类。,一个类只要继承了 Thread 类,此类就称为多线程实现类。要重写里面的 run 方法来实现自己的业务逻辑,如果想要启动一个线程,就需要调用其 start 方法。具体使用效果如下代码:
package com.haicoder.net.thread;
public class MyThread extends Thread {
private String name;
public MyThread(String name) {
this.name = name;
}
public void run(){
for(int i=0;i<5;i++){
System.out.println(name + "运行,i = " + i);
}
}
public static void main(String[] args) {
System.out.println("嗨客网(www.haicoder.net)");
MyThread myThread = new MyThread("线程A");
MyThread myThreadB = new MyThread("线程B");
myThread.start();
myThreadB.start();
}
}
运行结果如下图:
从上图的运行结果我们可以看到,实现了多线程机制,控制台输出的数据不是按照代码的编写顺序来打印的,Java 的线程是抢占式的,谁获取到 cpu 资源就执行谁。
如果你有心,多执行几次,你会发现你每次的执行结果都不一样。我们从代码中可以到,继承 Thread 类,就需要充写 run 方法,并且在启动线程的时候要调用 start 方法,而不是执行里面的 run 方法。并且 start 方法只能过被调用 1 次。如果调用多次,会抛出异常。
Runnable 是 Java.lang
包里面的一个接口,它的里面只定义了一个抽象的方法:
public void run();
具体的使用方法如下:
package com.haicoder.net.thread;
public class MyRunnable implements Runnable {
private String name;
public MyRunnable(String name) {
this.name = name;
}
@Override
public void run() {
for(int i=0;i<5;i++){
System.out.println(name + "运行,i = " + i);
}
}
public static void main(String[] args) {
MyRunnable myRunnable = new MyRunnable("线程A");
MyRunnable myRunnableB = new MyRunnable("线程B");
Thread thread1 = new Thread(myRunnable);
Thread thread2 = new Thread(myRunnableB);
thread1.start();
thread2.start();
}
}
运行效果图如下:
从上面运行结果可以看出,Runable 的执行是需要依赖 Thread。Thread 中封装了传递 Runable 的方法。想要启动线程,还是需要调用 Thread 的 start 方法。
Callable 接口是 Java.util.concurrent
包下面的接口,里面只定义了一个方法 V call() throws Exception;
通过前面两个多线程调用操作我们发现线程执行完之后获取不到其对应的返回值,我们可以通过实现 callable 接口生产多线程,并且获取到每个线程的返回值 Future。具体实现如下:
package com.haicoder.net.thread;
import Java.util.concurrent.Callable;
import Java.util.concurrent.FutureTask;
public class MyCallable implements Callable<String> {
@Override
public String call() throws Exception {
return "call 可以获取返回值";
}
public static void main(String[] args) throws Exception {
System.out.println("嗨客网(www.haicoder.net)");
MyCallable myCallable = new MyCallable();
FutureTask<String> futureTask = new FutureTask<String>(myCallable);
new Thread(futureTask).start();
System.out.println(futureTask.get());
}
}
运行结果如下图:
从上面的运行代码可以看出,使用 callable 线程生成接口的时候,也是需要用到 Thread 类的。和 Callable 一起使用到时候,需要用 FutureTask 来接受返回数据。