Version: Next
线程创建
Thread、Runnable、Callable
创建线程的三种方式:
Thread
类:继承Thread类Runnable
接口:实现Runnable接口Callable
接口:实现Callable接口
继承Thread类
自身实现了
Runnable
接口
步骤:
- 自定义线程类继承
Thread
类- 重写
run()
方法,编写线程执行体- 创建线程对象,调用
start()
方法启动线程
public class Demo01Thread extends Thread {
@Override
public void run() {
super.run();
for (int i = 0; i < 20; i++) {
System.out.println("run线程体 -> " + i);
}
}
public static void main(String[] args) {
//主线程
//创建一个线程对象
Demo01Thread thread = new Demo01Thread();
//调用start()方法,开启线程
thread.start();
for (int i = 0; i < 20; i++) {
System.out.println("主线程 ->" + i);
}
}
}
主线程 ->0
run线程体 -> 0
主线程 ->1
run线程体 -> 1
主线程 ->2
run线程体 -> 2
主线程 ->3
run线程体 -> 3
主线程 ->4
run线程体 -> 4
主线程 ->5
run线程体 -> 5
主线程 ->6
run线程体 -> 6
主线程 ->7
run线程体 -> 7
主线程 ->8
主线程 ->9
run线程体 -> 8
主线程 ->10
主线程 ->11
主线程 ->12
主线程 ->13
主线程 ->14
主线程 ->15
主线程 ->16
主线程 ->17
主线程 ->18
主线程 ->19
run线程体 -> 9
run线程体 -> 10
run线程体 -> 11
run线程体 -> 12
run线程体 -> 13
run线程体 -> 14
run线程体 -> 15
run线程体 -> 16
run线程体 -> 17
run线程体 -> 18
run线程体 -> 19
可以看到线程交替运行
实现Runnable接口
步骤
- 定义自己的类,实现
Runnable
接口- 实现
run()
方法,编写线程执行体- 创建线程对象,传入
Runnable
实现类对象,new Thread(Xxx)
- 调用
start()
方法启动线程
public class Demo02Runnable implements Runnable{
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println("run方法 -> " + i);
}
}
public static void main(String[] args) {
Demo02Runnable myRunnable = new Demo02Runnable();
//穿件线程对象,通过线程对象来开启我们的线程,代理
// Thread构造方法可以接受一个实现Runnable接口的类
new Thread(myRunnable).start();
for (int i = 0; i < 10; i++) {
System.out.println("主进程 -> " + i);
}
}
}
主进程 -> 0
run方法 -> 0
主进程 -> 1
run方法 -> 1
主进程 -> 2
run方法 -> 2
run方法 -> 3
主进程 -> 3
run方法 -> 4
主进程 -> 4
run方法 -> 5
主进程 -> 5
run方法 -> 6
主进程 -> 6
run方法 -> 7
主进程 -> 7
主进程 -> 8
run方法 -> 8
主进程 -> 9
run方法 -> 9
初识并发问题
public class Demo03Multi implements Runnable {
private int ticketNum = 10;
@Override
public void run() {
while (true) {
if (ticketNum <= 0) {
System.out.println("卖完了");
break;
}
System.out.println(Thread.currentThread().getName() +
"拿到了第" +
ticketNum-- +
"张票");
}
try {
//模拟延时
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
Demo03Multi demo03 = new Demo03Multi();
new Thread(demo03, "thread1").start();
new Thread(demo03, "thread2").start();
new Thread(demo03, "thread3").start();
}
}
thread1拿到了第9张票
thread3拿到了第9张票
thread2拿到了第10张票
thread3拿到了第7张票
thread1拿到了第8张票
thread3拿到了第5张票
thread2拿到了第6张票
thread3拿到了第3张票
thread1拿到了第4张票
卖完了
thread3拿到了第1张票
卖完了
thread2拿到了第2张票
卖完了
可以看到线程1和线程3都拿到第9张票,这说明多个线程同时操作一个资源时可能出现错误,称为
线程不安全
使用Lambda表达式书写
public class Demo05MultiWithLambda {
private static int ticketNum = 10;
public static void main(String[] args) {
new Thread(() -> {
while (true) {
if (ticketNum <= 0) {
System.out.println("卖完了");
break;
}
System.out.println(Thread.currentThread().getName() +
"拿到了第" +
ticketNum-- +
"张票");
}
try {
//模拟延时
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
},"t1").start();
}
}
实现Callable接口
步骤:
- 实现
Callable
接口,需要返回值类型- 重写
call()
方法,需要抛出异常- 创建目标对象
- 创建执行服务:
ExecutorService ser = Executors.newFixedThreadPool(1);
- 提交执行:
Future<Boolean> result1 = ser.submit(t1)
- 获取结果:
boolean r1 = result1.get()
- 关闭服务:
ser.shutdownNow()
public class Demo04Callable implements Callable {
@Override
public Boolean call() throws Exception {
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread().getName() + " | callable call() -> " + i);
}
return true;
}
public static void main(String[] args) throws ExecutionException, InterruptedException {
Demo04Callable t1 = new Demo04Callable();
Demo04Callable t2 = new Demo04Callable();
Demo04Callable t3 = new Demo04Callable();
//创建执行服务
ExecutorService service = Executors.newFixedThreadPool(3);
//提交执行
Future<Boolean> result1 = service.submit(t1);
Future<Boolean> result2 = service.submit(t2);
Future<Boolean> result3 = service.submit(t3);
//获取结果
Boolean resultBool1 = result1.get();
Boolean resultBool2 = result2.get();
Boolean resultBool3 = result3.get();
//关闭服务
service.shutdown();
}
}
pool-1-thread-1 | callable call() -> 0
pool-1-thread-1 | callable call() -> 1
pool-1-thread-1 | callable call() -> 2
pool-1-thread-1 | callable call() -> 3
pool-1-thread-1 | callable call() -> 4
pool-1-thread-1 | callable call() -> 5
pool-1-thread-2 | callable call() -> 0
pool-1-thread-2 | callable call() -> 1
pool-1-thread-2 | callable call() -> 2
pool-1-thread-2 | callable call() -> 3
pool-1-thread-2 | callable call() -> 4
pool-1-thread-2 | callable call() -> 5
pool-1-thread-2 | callable call() -> 6
pool-1-thread-2 | callable call() -> 7
pool-1-thread-3 | callable call() -> 0
pool-1-thread-2 | callable call() -> 8
pool-1-thread-1 | callable call() -> 6
pool-1-thread-1 | callable call() -> 7
pool-1-thread-1 | callable call() -> 8
pool-1-thread-1 | callable call() -> 9
pool-1-thread-2 | callable call() -> 9
pool-1-thread-3 | callable call() -> 1
pool-1-thread-3 | callable call() -> 2
pool-1-thread-3 | callable call() -> 3
pool-1-thread-3 | callable call() -> 4
pool-1-thread-3 | callable call() -> 5
pool-1-thread-3 | callable call() -> 6
pool-1-thread-3 | callable call() -> 7
pool-1-thread-3 | callable call() -> 8
pool-1-thread-3 | callable call() -> 9
小结
继承Thread类
- 子类继承Thread类具备多线程能力
- 启动线程:子类对象.start()
不建议使用:避免OOP单继承局限性
实现Runnable接口
- 实现接口Runnable具有多线程能力
- 启动线程:传入目标对象 ->
new Thread(目标对象).start()
推荐使用:避免单继承局限性,灵活方便,方便同一个对象被多个线程使用