Java 多线程 - 学习笔记
Posted 笑虾
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java 多线程 - 学习笔记相关的知识,希望对你有一定的参考价值。
Java 多线程 - 学习笔记
Thread 类
Java 只能单继承,所以一般不会这么用。
- 直接继承 Thread 重写 run
- 再调 start() 启动
public class ThreadDemo extends Thread
private int i = 10;
@Override
public void run()
while (i > 0)
System.out.println("线程 " + Thread.currentThread().getName() + " 输出:" + i);
i--;
public static void main(String[] args) throws InterruptedException
System.out.println("线程 " + Thread.currentThread().getName() + "开始。");
ThreadDemo threadDemo = new ThreadDemo();
threadDemo.start();
Runnable 接口
- 实现 Runnable 重写 run
- 没有返回值
- 启动:两种
3.1. 丢进Thread
再.start()
3.2. 用ExecutorService
启动线程
public class RunnableDemo implements Runnable
private int i = 10;
@Override
public void run()
while (i > 0)
System.out.println("线程 " + Thread.currentThread().getName() + " 输出:" + i);
i--;
public static void main(String[] args) throws InterruptedException
// 用 Thread.start() 启动
System.out.println("线程 " + Thread.currentThread().getName() + "开始。");
new Thread(new RunnableDemo()).start();
// Runnable 也可以用 ExecutorService 启动线程,比 Thread 的 start() 更好
ExecutorService executor = Executors.newCachedThreadPool();
RunnableDemo runnableDemo = new RunnableDemo();
executor.execute(runnableDemo);
executor.shutdown();
Callable 接口
- 实现
Callable<T>
重写call
- 有返回值。返回值类型
T
- 启动三种:
3.1. 丢进Thread
再.start()
3.2. 用ExecutorService
启动线程
3.3.new Callable()
先丢进FutureTask
再交给ExecutorService
提交 Future<T>.get()
获取线程返回值
public class CallableDemo implements Callable<Integer>
private int i = 10;
@Override
public Integer call() throws Exception
while (i > 0)
System.out.println("线程 " + Thread.currentThread().getName() + " 输出:" + i);
i--;
return 999;
public static void main(String[] args) throws InterruptedException, ExecutionException
System.out.println("线程 " + Thread.currentThread().getName() + "开始。");
// FutureTask 是 Runnable 的实现,所以也可以丢给 Thread().start();
new Thread(new FutureTask<Integer>(new CallableDemo()), "AAA").start();
// Callable 只能用 ExecutorService 启动线程
ExecutorService executor = Executors.newCachedThreadPool();
Future<Integer> submit = executor.submit(new CallableDemo());
executor.shutdown();
System.out.println("线程结束,返回:" + submit.get());
// 先丢进 FutureTask 再提交
ExecutorService executor2 = Executors.newCachedThreadPool();
FutureTask<Integer> futureTask = new FutureTask<Integer>(new CallableDemo());
executor2.submit(futureTask);
executor2.shutdown();
System.out.println("线程结束,返回:" + futureTask.get());
多线程虚假唤醒
对比两个方法对wait();
的判断处理。
吃粉()
的判断在if 代码块
中,下次醒来时,会直接往下走。但我们想要的是被唤醒后,首先判断是否满足条件,满足的情况下才处理业务。所以这里会有漏网之鱼。
下粉()
因为用的while
判断,下次原地醒来,继续走完代码块,又回头判断一次。必须完足条件才会继续,不存在漏网之鱼。
class 牛肉粉
private int i = 0;
public synchronized void 吃粉() throws InterruptedException
if (i == 0)
// 在 wait() 调用时,释放锁,就地睡觉。
this.wait();
// 被唤醒时,原地站起来紧跟在 wait()后继续执行。
System.out.println(i + " 碗库存!" + Thread.currentThread().getName() + " 吃了一碗粉。");
i--;
this.notifyAll();
public synchronized void 下粉() throws InterruptedException
while (i != 0)
this.wait();
System.out.println(i + " 碗库存!" + Thread.currentThread().getName() + " 下了一碗粉。");
i++;
this.notifyAll();
参考资料
以上是关于Java 多线程 - 学习笔记的主要内容,如果未能解决你的问题,请参考以下文章