Java多线程详解
进程和线程
示例代码:
package com.gavin.demo01;
public class TestThread extends Thread{
@Override
public void run() {
//run方体线程
for (int i = 0; i < 20; i++) {
System.out.println("我在看代码---" + i);
}
}
public static void main(String[] args) {
//main方法是一个主线程
//创建一个线程对象
TestThread testThread = new TestThread();
//调用start方法开启线程
testThread.start();
for (int i = 0; i < 1000 ; i++) {
System.out.println("我在学习多线程---" + i);
}
}
}
执行结果:
可以看出run方法和main方法是同时执行的,都由CPU调度,会出现线程抢夺的问题
使用多线程下载图片示例代码:
package com.gavin.demo01;
import org.apache.commons.io.FileUtils;
import java.io.File;
import java.io.IOException;
import java.net.URL;
public class TestThread2 extends Thread{
private String url;
private String name;
public TestThread2(String url, String name) {
this.url = url;
this.name = name;
}
@Override
public void run() {
WebDownLoad webDownLoad = new WebDownLoad();
webDownLoad.down(url, name);
System.out.println("下载文件为:" + name);
}
public static void main(String[] args) {
TestThread2 testThread = new TestThread2("https://img-blog.csdnimg.cn/ff1034bf4ec944ed9b9fefb5d9bbeb2c.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAR2F2aW5DaGVuXw==,size_20,color_FFFFFF,t_70,g_se,x_16#pic_center", "1.jpg");
TestThread2 testThread2 = new TestThread2("https://img-blog.csdnimg.cn/98a80c1487354509baa94b1522e22fe6.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAR2F2aW5DaGVuXw==,size_20,color_FFFFFF,t_70,g_se,x_16#pic_center", "2.jpg");
TestThread2 testThread3 = new TestThread2("https://img-blog.csdnimg.cn/30244b9ad1eb40d6a2c6f757e458d343.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAR2F2aW5DaGVuXw==,size_20,color_FFFFFF,t_70,g_se,x_16#pic_center", "3.jpg");
testThread.start();
testThread2.start();
testThread3.start();
}
}
class WebDownLoad{
public void down(String url, String name) {
try {
FileUtils.copyURLToFile(new URL(url), new File(name));
} catch (IOException e) {
e.printStackTrace();
System.out.println("IO异常,down方法出错");
}
}
}
执行结果:
可以看出,程序启动后三个线程是同时执行的,并不是按照从上往下的顺序执行的,所以才出现图中所示的打印顺序。
实现Runnable接口
示例代码:
package com.gavin.demo01;
public class TestRunnable implements Runnable{
@Override
public void run() {
//run方法线程
for (int i = 0; i < 20; i++) {
System.out.println("我在看代码---" + i);
}
}
public static void main(String[] args) {
//main方法是一个主线程
//创建一个线程对象
TestRunnable testRunnable = new TestRunnable();
//传入实现Runnable接口的类
Thread thread = new Thread(testRunnable);
//调用start方法开启线程
thread.start();
for (int i = 0; i < 1000 ; i++) {
System.out.println("我在学习多线程---" + i);
}
}
}
执行结果:
使用实现Runnable接口来下载图片
示例代码:
package com.gavin.demo01;
import org.apache.commons.io.FileUtils;
import java.io.File;
import java.io.IOException;
import java.net.URL;
public class TestRunnable2 implements Runnable{
private String url;
private String name;
public TestRunnable2(String url, String name) {
this.url = url;
this.name = name;
}
@Override
public void run() {
WebDownLoad2 webDownLoad2 = new WebDownLoad2();
webDownLoad2.down(url, name);
System.out.println("下载文件为:" + name);
}
public static void main(String[] args) {
TestThread2 testThread = new TestThread2("https://img-blog.csdnimg.cn/ff1034bf4ec944ed9b9fefb5d9bbeb2c.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAR2F2aW5DaGVuXw==,size_20,color_FFFFFF,t_70,g_se,x_16#pic_center", "1.jpg");
TestThread2 testThread2 = new TestThread2("https://img-blog.csdnimg.cn/98a80c1487354509baa94b1522e22fe6.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAR2F2aW5DaGVuXw==,size_20,color_FFFFFF,t_70,g_se,x_16#pic_center", "2.jpg");
TestThread2 testThread3 = new TestThread2("https://img-blog.csdnimg.cn/30244b9ad1eb40d6a2c6f757e458d343.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAR2F2aW5DaGVuXw==,size_20,color_FFFFFF,t_70,g_se,x_16#pic_center", "3.jpg");
Thread thread = new Thread(testThread);
Thread thread2 = new Thread(testThread2);
Thread thread3 = new Thread(testThread3);
thread.start();
thread2.start();
thread3.start();
}
}
class WebDownLoad2{
public void down(String url, String name) {
try {
FileUtils.copyURLToFile(new URL(url), new File(name));
} catch (IOException e) {
e.printStackTrace();
System.out.println("IO异常,down方法出错");
}
}
}
执行结果:
初识并发问题
多线程操作同一个对象的示例代码:
package com.gavin.Demo02;
//多线程同时操作一个对象
//买火车票的例子
public class TestRunnable3 implements Runnable{
//票数
private int ticketNumber = 10;
@Override
public void run() {
while (true) {
if (ticketNumber <= 0) {
break;
}
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "-->拿到了第" + ticketNumber-- + "张票");
}
}
public static void main(String[] args) {
TestRunnable3 testRunnable = new TestRunnable3();
Thread thread = new Thread(testRunnable, "小明");
thread.start();
Thread thread2 = new Thread(testRunnable, "老师");
thread2.start();
Thread thread3 = new Thread(testRunnable, "黄牛党");
thread3.start();
}
}
执行结果:
可以看出小明和黄牛党同时抢到了第9张票,小明和老师同时抢到了第5张票,出现了很大的问题,这个需要以后并发的知识解决。
龟兔赛跑例子
示例代码:
package com.gavin.Demo02;
//模拟龟兔赛跑的例子
public class Race implements Runnable{
private static String winner;
@Override
public void run() {
for (int i = 1; i <= 100; i++) {
//让兔子休息5毫秒
if (Thread.currentThread().getName().equals("兔子") && i % 10 == 0) {
try {
Thread.sleep(5);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName() + "-->跑了" + i + "步");
Boolean flag = gameOver(i);
if (flag) {
break;
}
}
}
public Boolean gameOver(int steps) {
if (winner != null) {
return true;
} else {
if (steps >= 100) {
winner = Thread.currentThread().getName();
System.out.println("胜利者是:" + winner);
return true;
}
}
return false;
}
public static void main(String[] args) {
Race race = new Race();
Thread thread = new Thread(race, "乌龟");
Thread thread2 = new Thread(race, " 兔子");
thread.start();
thread2.start();
}
}
执行结果:
用一段代码还原了经典的龟兔赛跑故事,属实不错!
实现Callable接口
示例代码:
package com.gavin.Demo02;
import org.apache.commons.io.FileUtils;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.concurrent.*;
//实现Callable接口,用来下载图片
public class TestCallable implements Callable<Boolean> {
private String url;
private String name;
public TestCallable(String url, String name) {
this.url = url;
this.name = name;
}
@Override
public Boolean call() throws Exception {
WebDownLoad2 webDownLoad = new WebDownLoad2();
webDownLoad.down(url, name);
System.out.println("下载文件为:" + name);
return true;
}
public static void main(String[] args) throws ExecutionException, InterruptedException {
TestCallable testCallable = new TestCallable("https://img-blog.csdnimg.cn/ff1034bf4ec944ed9b9fefb5d9bbeb2c.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAR2F2aW5DaGVuXw==,size_20,color_FFFFFF,t_70,g_se,x_16#pic_center", "1.jpg");
TestCallable testCallable2 = new TestCallable("https://img-blog.csdnimg.cn/98a80c1487354509baa94b1522e22fe6.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAR2F2aW5DaGVuXw==,size_20,color_FFFFFF,t_70,g_se,x_16#pic_center", "2.jpg");
TestCallable testCallable3 = new TestCallable("https://img-blog.csdnimg.cn/30244b9ad1eb40d6a2c6f757e458d343.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAR2F2aW5DaGVuXw==,size_20,color_FFFFFF,t_70,g_se,x_16#pic_center", "3.jpg");
//创建执行服务
ExecutorService executorService = Executors.newFixedThreadPool(3);
//提交执行
Future<Boolean> r1 = executorService.submit(testCallable);
Future<Boolean> r2 = executorService.submit(testCallable2);
Future<Boolean> r3 = executorService.submit(testCallable3);
//获取结果
boolean rs1 = r1.get();
boolean rs2 = r1.get();
boolean rs3 = r1.get();
System.out.println(rs1);
System.out.println(rs2);
System.out.println(rs3);
//关闭服务
executorService.shutdown();
}
}
class WebDownLoad2{
public void down(String url, String name) {
try {
FileUtils.copyURLToFile(new URL(url), new File(name));
} catch (IOException e) {
e.printStackTrace();
System.out.println("IO异常,down方法出错");
}
}
}
执行结果:
静态代理模式
示例代码:
package com.gavin.Demo03;
public class StaticProxy {
public static void main(String[] args) {
WeddingCompany weddingCompany = new WeddingCompany(new You());
weddingCompany.HappyMarry();
}
}
interface Marry {
void HappyMarry();
}
class You implements Marry {
@Override
public void HappyMarry() {
System.out.println("今天要Happy哦!!!");
}
}
class WeddingCompany implements Marry {
private Marry target;
public WeddingCompany(Marry target) {
this.target = target;
}
@Override
public void HappyMarry() {
before();
this.target.HappyMarry();
after();
}
public void before() {
System.out.println("昨天Happy!!!");
}
public void after() {
System.out.println("明天Happy!!!");
}
}
执行结果:
可以看出WeddingCompany作为You类的静态代理,不仅可以调用本身的方法,也可以调用代理对象的方法,这就是静态代理的思想。
线程状态
线程的停止
使用自己定义的方法用来停止线程
示例代码:
package com.gavin.Demo04;
public class TestStop implements Runnable{
//设置一个标识用来停止线程
private boolean flag = true;
@Override
public void run() {
int i = 0;
while (flag) {
System.out.println("执行了-->" + i++ + "次");
}
}
//设一个公开的方法停止线程,转换标志位
public void stop() {
this.flag = false;
}
public static void main(String[] args) {
TestStop testStop = new TestStop();
Thread thread = new Thread(testStop);
thread.start();
for (int i = 0; i <= 100 ; i++) {
System.out.println("main执行了-->" + i + "次");
if (i == 90) {
//调用自己的stop方法停止线程
testStop.stop();
System.out.println("线程已经停止了");
}
}
}
}
执行结果:
可以看出当主线程执行到第90次时,调用自定义的线程停止方法,停止了自定义的线程,此时自定义的线程只执行了63次。
线程休眠
使用Thread.sleep方法完成倒计时功能
示例代码:
package com.gavin.Demo04;
public class TestSleep {
public static void main(String[] args) {
try {
tenDown();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//使用Thread.sleep方法完成倒计时功能
public static void tenDown() throws InterruptedException {
int num = 10;
while (true) {
Thread.sleep(1000);
System.out.println(num);
num --;
if (num == 0) {
break;
}
}
}
}
执行结果:
使用Thread.sleep方法打印当前系统时间
示例代码:
package com.gavin.Demo04;
import java.text.SimpleDateFormat;
import java.util.Date;
public class TestSleep2 {
//使用Thread.sleep方法打印当前系统时间
public static void main(String[] args) throws InterruptedException {
Date startTime = new Date(System.currentTimeMillis());
while (true) {
Thread.sleep(1000);
System.out.println(new SimpleDateFormat("HH:mm:ss").format(startTime));
startTime = new Date(System.currentTimeMillis());
}
}
}
执行结果:
线程礼让
示例代码:
package com.gavin.Demo04;
public class TestYield {
public static void main(String[] args) {
MyYield myYield = new MyYield();
Thread thread = new Thread(myYield, "a");
Thread thread2 = new Thread(myYield, "b");
thread.start();
thread2.start();
}
}
class MyYield implements Runnable {
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + "线程开始执行");
//线程礼让
Thread.yield();
System.out.println(Thread.currentThread().getName() + "线程停止执行");
}
}
执行结果:
可以看出程序执行时,a线程礼让了b线程
线程强制执行
示例代码:
package com.gavin.Demo04;
public class TestJoin implements Runnable{
@Override
public void run() {
for (int i = 1; i <= 100; i++) {
System.out.println("线程VIP来了-->" + i);
}
}
public static void main(String[] args) throws InterruptedException {
TestJoin testJoin = new TestJoin();
Thread thread = new Thread(testJoin);
thread.start();
//主线程开始执行
for (int i = 1; i <= 500; i++) {
if (i == 20) {
//线程插队
thread.join();
}
System.out.println("main-->" + i);
}
}
}
执行结果:
观测线程状态
示例代码:
package com.gavin.state;
public class TestState {
public static void main(String[] args) {
Thread thread = new Thread(() -> {
for (int i = 0; i < 5; i++) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("//");
});
//观察线程状态
Thread.State state = thread.getState();
System.out.println(state); //NEW
//观察线程启动后状态
thread.start();
state = thread.getState();
System.out.println(state); //RUN
//只要线程不终止,就会一直输出状态
while (state != Thread.State.TERMINATED) {
try {
Thread.sleep(100);
//更新线程状态
state = thread.getState();
//输出状态
System.out.println(state);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
执行结果:
线程的优先级
示例代码:
package com.gavin.state;
public class TestPriority {
public static void main(String[] args) {
System.out.println(Thread.currentThread().getName() + "-->" + Thread.currentThread().getPriority());
MyPriority myPriority = new MyPriority();
Thread thread = new Thread(myPriority);
Thread thread2 = new Thread(myPriority);
Thread thread3 = new Thread(myPriority);
Thread thread4 = new Thread(myPriority);
Thread thread5 = new Thread(myPriority);
Thread thread6 = new Thread(myPriority);
//先设置线程的优先级,再启动线程
thread.start();
thread2.setPriority(3);
thread2.start();
thread3.setPriority(Thread.MAX_PRIORITY); //Thread.MAX_PRIORITY = 10
thread3.start();
thread4.setPriority(Thread.MIN_PRIORITY); //Thread.MIN_PRIORITY = 1
thread4.start();
thread5.setPriority(7);
thread5.start();
thread6.setPriority(8);
thread6.start();
}
}
class MyPriority implements Runnable{
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + "-->" + Thread.currentThread().getPriority());
}
}
执行结果:
可以看出,有时候线程的执行顺序不是按照设定的优先级执行了,这是因为现在的CPU运算速度很块,以及CPU算法的优化,这几个线程几乎在同一时间执行的,所有打印出来的优先级不是自己设置的优先级。
守护线程
示例代码:
package com.gavin.state;
public class TestDaemon {
public static void main(String[] args) {
God god = new God();
You you = new You();
Thread thread = new Thread(god);
//默认是false表示是用户线程,正常的线程都是用户线程
thread.setDaemon(true);
//上帝手护线程开启
thread.start();
Thread thread2 = new Thread(you);
//自己的用户线程
thread2.start();
}
}
class God implements Runnable {
@Override
public void run() {
while (true) {
System.out.println("上帝保佑者你");
}
}
}
class You implements Runnable {
@Override
public void run() {
for (int i = 0; i < 36500; i++) {
System.out.println("每一天都活得很开心哦!");
}
System.out.println("永别了世界!GoodBy~~~");
}
}
执行结果:
线程同步机制
并发的解释:
线程锁的解释:
线程不安全案例
银行取钱案例
示例代码:
package com.gavin.syn;
public class UnsafeBank {
public static void main(String[] args) {
Account account = new Account("结婚基金", 100);
Drawing drawing = new Drawing(account, 50, "你");
Drawing drawing2 = new Drawing(account, 100, "你媳妇");
drawing.start();
drawing2.start();
}
}
class Account {
String name;
int balance;
public Account(String name, int balance) {
this.name = name;
this.balance = balance;
}
}
class Drawing extends Thread {
Account account;
//取了多少钱
int drawingMoney;
//现在手里还有多少钱
int nowMoney;
public Drawing(Account account, int drawingMoney, String name) {
super(name);
this.account = account;
this.drawingMoney = drawingMoney;
}
@Override
public void run() {
if (account.balance - drawingMoney < 0) {
System.out.println(Thread.currentThread().getName() + "钱不够,取不了");
return;
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//卡内余额
account.balance = account.balance - drawingMoney;
//你手里的钱
nowMoney = nowMoney + drawingMoney;
System.out.println(account.name + "余额为:" + account.balance);
System.out.println(this.getName() + "手里的钱:" + nowMoney);
}
}
执行结果:
可以看出,两个线程同时去取钱,余额成了负数,出现了重大的问题。
synchronized同步方法
使用synchronized优化抢票代码:
package com.gavin.Demo02;
//多线程同时操作一个对象
//买火车票的例子
public class TestRunnable3 implements Runnable{
//票数
private int ticketNumber = 10;
@Override
public synchronized void run() {
while (true) {
if (ticketNumber <= 0) {
break;
}
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "-->拿到了第" + ticketNumber-- + "张票");
}
}
public static void main(String[] args) {
TestRunnable3 testRunnable = new TestRunnable3();
Thread thread = new Thread(testRunnable, "小明");
thread.start();
Thread thread2 = new Thread(testRunnable, "老师");
thread2.start();
Thread thread3 = new Thread(testRunnable, "黄牛党");
thread3.start();
}
}
执行结果:
synchronized同步块
使用synchronized同步块优化银行取钱代码:
package com.gavin.syn;
public class UnsafeBank {
public static void main(String[] args) {
Account account = new Account("结婚基金", 100);
Drawing drawing = new Drawing(account, 50, "你");
Drawing drawing2 = new Drawing(account, 100, "你媳妇");
drawing.start();
drawing2.start();
}
}
class Account {
String name;
int balance;
public Account(String name, int balance) {
this.name = name;
this.balance = balance;
}
}
class Drawing extends Thread {
Account account;
//取了多少钱
int drawingMoney;
//现在手里还有多少钱
int nowMoney;
public Drawing(Account account, int drawingMoney, String name) {
super(name);
this.account = account;
this.drawingMoney = drawingMoney;
}
@Override
public void run() {
synchronized (account) {
if (account.balance - drawingMoney < 0) {
System.out.println(Thread.currentThread().getName() + "钱不够,取不了");
return;
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//卡内余额
account.balance = account.balance - drawingMoney;
//你手里的钱
nowMoney = nowMoney + drawingMoney;
System.out.println(account.name + "余额为:" + account.balance);
System.out.println(this.getName() + "手里的钱:" + nowMoney);
}
}
}
执行结果:
CopyOnWriteArrayList集合
CopyOnWriteArrayList集合是线程安全的,具体请看下面的示例代码:
package com.gavin.syn;
import java.util.concurrent.CopyOnWriteArrayList;
public class TestJUC {
public static void main(String[] args) {
CopyOnWriteArrayList<String> arrayList = new CopyOnWriteArrayList<>();
for (int i = 0; i < 10000; i++) {
new Thread(() -> {
arrayList.add(Thread.currentThread().getName());
}).start();
}
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("CopyOnWriteArrayList集合长度为:" + arrayList.size());
}
}
执行结果:
死锁
示例代码:
package com.gavin.thread;
public class DeadLock {
public static void main(String[] args) {
Makeup makeup = new Makeup(0, "小兰");
Makeup makeup2 = new Makeup(1, "小美");
makeup.start();
makeup2.start();
}
}
//口红类
class Lipstick {
}
//镜子类
class Mirror {
}
class Makeup extends Thread {
static Lipstick lipstick = new Lipstick();
static Mirror mirror = new Mirror();
int choice;
String girlName;
Makeup(int choice, String girlName) {
this.choice = choice;
this.girlName = girlName;
}
@Override
public void run() {
try {
makeup();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void makeup() throws InterruptedException {
if (choice == 0) {
synchronized (lipstick) {
System.out.println(this.girlName + "拿到口红");
Thread.sleep(1000);
synchronized (mirror) {
System.out.println(this.girlName + "拿到镜子");
}
}
} else {
synchronized (mirror) {
System.out.println(this.girlName + "拿到镜子");
Thread.sleep(2000);
synchronized (lipstick) {
System.out.println(this.girlName + "拿到口红");
}
}
}
}
}
执行结果:
可以看出程序进入了死锁状态
产生死锁的四个必要条件:
Lock锁
示例代码:
package com.gavin.thread;
import java.util.concurrent.locks.ReentrantLock;
public class TestLock {
public static void main(String[] args) {
TestLock2 testLock2 = new TestLock2();
Thread thread = new Thread(testLock2);
Thread thread2 = new Thread(testLock2);
Thread thread3 = new Thread(testLock2);
thread.start();
thread2.start();
thread3.start();
}
}
class TestLock2 implements Runnable {
int tickNumber = 10;
//定义lock锁
private final ReentrantLock reentrantLock = new ReentrantLock();
@Override
public void run() {
while (true) {
try {
//加锁
reentrantLock.lock();
if (tickNumber > 0) {
System.out.println("剩余票数:" + tickNumber --);
} else {
break;
}
} catch (Exception e) {
e.printStackTrace();
} finally {
//线程执行完解锁
reentrantLock.unlock();
}
}
}
}
执行结果:
synchronized和Lock锁的区别:
生产者和消费者问题
应用场景:
管程法
示例代码:
package com.gavin.thread;
public class TestPC {
public static void main(String[] args) {
SynContainer synContainer = new SynContainer();
Product product = new Product(synContainer);
Customer customer = new Customer(synContainer);
product.start();
customer.start();
}
}
class Product extends Thread {
SynContainer synContainer;
Product(SynContainer synContainer) {
this.synContainer = synContainer;
}
@Override
public void run() {
for (int i = 0; i < 100; i++) {
synContainer.push(new Chicken(i));
System.out.println("生产了" + i + "只鸡");
}
}
}
class Customer extends Thread {
SynContainer synContainer;
Customer(SynContainer synContainer) {
this.synContainer = synContainer;
}
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println("消费了" + synContainer.pop().id + "只鸡");
}
}
}
class Chicken {
int id;
Chicken(int id) {
this.id = id;
}
}
class SynContainer {
Chicken[] chickens = new Chicken[10];
int count = 0;
public synchronized void push(Chicken chicken) {
//如果容器满了,就等待消费者消费
if (count == chickens.length) {
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
chickens[count] = chicken;
count++;
//可以通知消费者消费了
this.notifyAll();
}
public synchronized Chicken pop() {
//没有就等待生产者生产
if (count == 0) {
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//有就消费
count--;
Chicken chicken = chickens[count];
//通知生产者生产
this.notifyAll();
return chicken;
}
}
执行结果:
信号灯法:
示例代码:
package com.gavin.thread;
public class TestPC2 {
public static void main(String[] args) {
TV tv = new TV();
Player player = new Player(tv);
Watcher watcher = new Watcher(tv);
player.start();
watcher.start();
}
}
class Player extends Thread{
TV tv;
Player(TV tv) {
this.tv = tv;
}
@Override
public void run() {
for (int i = 0; i < 20; i++) {
if (i % 2 == 0) {
this.tv.play("B站");
} else {
this.tv.play("抖音");
}
}
}
}
class Watcher extends Thread{
TV tv;
Watcher(TV tv) {
this.tv = tv;
}
@Override
public void run() {
for (int i = 0; i < 20; i++) {
this.tv.watch();
}
}
}
class TV {
//表演的节目名称
String voice;
//演员表演标识
boolean flag = true;
public synchronized void play(String voice) {
if (!flag) {
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("演员表演了:" + voice);
//通知观众观看
this.notifyAll();
this.voice = voice;
this.flag = !this.flag;
}
public synchronized void watch() {
if (flag) {
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("观众观看了:" + voice);
//通知演员表演
this.notifyAll();
this.flag = !this.flag;
}
}
执行结果:
线程池
示例代码:
package com.gavin.thread;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class TestPool {
public static void main(String[] args) {
//创建10个线程
ExecutorService service = Executors.newFixedThreadPool(10);
//执行线程
service.execute(new MyThread());
service.execute(new MyThread());
service.execute(new MyThread());
service.execute(new MyThread());
service.execute(new MyThread());
//关闭线程
service.shutdown();
}
}
class MyThread implements Runnable {
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
}
}
执行结果:
总结
三种创建线程的方法
示例代码:
package com.gavin.thread;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
public class ThreadNew {
public static void main(String[] args) {
new MyThread1().start();
new Thread(new MyThread2()).start();
FutureTask<Integer> futureTask = new FutureTask<Integer>(new MyThread3());
new Thread(futureTask).start();
try {
Integer number = futureTask.get();
System.out.println(number);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
}
class MyThread1 extends Thread {
@Override
public void run() {
System.out.println("MyThread1");
}
}
class MyThread2 implements Runnable {
@Override
public void run() {
System.out.println("MyThread2");
}
}
class MyThread3 implements Callable<Integer> {
@Override
public Integer call() throws Exception {
System.out.println("MyThread3");
return 100;
}
}
执行结果: