目录
Thread、Runnable、Callable的使用
Thread的简单实现
public class Demo {
public static void main(String[] args) throws InterruptedException {
// 新建子线程
MyThread myThread = new MyThread();
// 启动子线程
myThread.start();
// 效果对比
String threadName = Thread.currentThread().getName();
for (int i = 0; i < 10; i++) {
Thread.sleep(100);
System.out.println(threadName + "--------" + i);
}
}
}
// 继承Thread
class MyThread extends Thread {
@Override
public void run() {
String threadName = Thread.currentThread().getName();
for (int i = 0; i < 10; i++) {
try {
Thread.sleep(100);
System.out.println(threadName + "--------" + i);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
执行效果:
main--------0
Thread-0--------0
main--------1
Thread-0--------1
Thread-0--------2
main--------2
Thread-0--------3
main--------3
main--------4
Thread-0--------4
Thread-0--------5
main--------5
main--------6
Thread-0--------6
main--------7
Thread-0--------7
Thread-0--------8
main--------8
main--------9
Thread-0--------9
Runnable的简单实现
public class Demo {
public static void main(String[] args) throws InterruptedException {
// 新建任务
MyRunnable run = new MyRunnable();
// 新建线程,设置任务
Thread thread = new Thread(run);
// 启动子线程
thread.start();
// 效果对比
String threadName = Thread.currentThread().getName();
for (int i = 0; i < 10; i++) {
Thread.sleep(100);
System.out.println(threadName + "--------" + i);
}
}
}
// 实现Runnable接口
class MyRunnable implements Runnable {
@Override
public void run() {
String threadName = Thread.currentThread().getName();
for (int i = 0; i < 10; i++) {
try {
Thread.sleep(100);
System.out.println(threadName + "--------" + i);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
Callable的简单实现
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
public class Demo {
public static void main(String[] args) throws InterruptedException, ExecutionException {
// 创建Callable
MyCallable call = new MyCallable(10);
// 创建任务
FutureTask<Integer> task = new FutureTask<Integer>(call);
// 新建线程,设置任务
Thread thread = new Thread(task);
// 启动子线程
thread.start();
long begin = System.currentTimeMillis();
System.out.println("已启动子线程");
// 调用get方法会阻塞用户线程,如不调用,用户线程会继续往下执行
Integer sum = task.get();
System.out.println("结果" + sum + ",耗时:" + (System.currentTimeMillis() - begin) / 1000);
}
}
// 实现Callable接口
class MyCallable implements Callable<Integer> {
private int num;
public MyCallable(int num) {
this.num = num;
}
@Override
public Integer call() throws Exception {
// 从 1 到 num 的合计
int sum = 0;
for (int i = 1; i <= num; i++) {
Thread.sleep(1000);
sum += i;
}
return sum;
}
}
已启动子线程
结果55,耗时:10
Thread与Runnable的优缺
Runnable相比Thread的优点
1.通过创建任务,然后给线程分配的方式来实现的多线程,更适合多个线程同时执行相同任务的情况
2.可以避免单继承所带来的的局限性
3.任务与线程分离,提高了程序的健壮性
4.线程池技术,接受Runnable,不接受Thread
Thread相比Runnable的优点
子线程任务仅使用一次时,使用匿名内部类的方式实现,代码较为简洁美观
public static void main(String[] args) {
// 匿名内部类 + lambda表达式
new Thread(() -> {
String threadName = Thread.currentThread().getName();
for (int i = 0; i < 10; i++) {
System.out.println(threadName + "--------" + i);
}
}).start();
}
Runnable与Callable的异同
- 相同点
- 都是接口
- 都可以编写多线程程序
- 都采用Thread.start()启动线程
- 不同点
- Runnable没有返回值;Callable可以返回执行结果
- Callable接口的call()允许抛出异常;Runnable的run()不能抛出