多线程学习
线程简介
程序------进程-------线程
-
线程是独立执行的路径
-
在程序运行中,即使没有自己创建线程,后台也会有多个线程,如主线程(main)\线程
-
main()称为主线程,是程序的入口,用于执行整个程序
-
在一个进程中,如果开辟了多个线程,线程的运行由调度器安排调度,调度器是与操作系统紧密相关的,先后顺序是不能人为干预的
-
对于同一份资源操作时,会存在资源抢夺的问题,需要加入并发控制
-
线程对带来额外的开销,如cpu调度时间,并发控制开销
-
每个线程在自己的内存交互,内存控制不当会造成数据不一致
线程创建
Thread、Runnable接口、Callable接口
继承Thread
-
自定义线程继承Thread类
-
重写 run()方法,编写线程执行体
-
创建线程对象,调用start()方法启动线程
package com.tan;
// 创建线程方式:继承Thread类,重写run()方法,调用start()开启线程
// 注意:线程开启不一定立即执行,由cpu调度
public class TestThread1 extends Thread{
@Override
public void run() {
// run()方法线程体
for (int i = 0; i < 10; i++) {
System.out.println("我再看代码===="+i);
}
}
public static void main(String[] args) {
// main线程,主线程
//创建一个线程对象
TestThread1 testThread1= new TestThread1();
// 调用start()方法开启线程
testThread1.start();
for (int i = 0; i < 10; i++) {
System.out.println("我在学习多线程==="+i);
}
}
}
package com.gentlesoft.oa.archives.controller;
import com.gentlesoft.oa.util.FileUtil;
import org.apache.commons.io.FileUtils;
import org.apache.poi.xwpf.usermodel.IRunBody;
import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
public class Person extends Thread{
// 联系Thread,实现多线程同步下载图片
private String url;
private String name ;
public Person(String url,String name){
this.url = url;
this.name = name;
}
@Override
public void run() {
WebDownLoader webDownLoader = new WebDownLoader();
try {
webDownLoader.downloader(url,name);
System.out.println("下载了 图片:"+name);
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
Person p3 = new Person("https://image.so.com/view?q=%E5%9B%BE%E7%89%87&listsrc=sobox&listsign=9f3a1eeb2c9fe66d36e55cf51f4b33ae&src=360pic_new_strong&correct=%E5%9B%BE%E7%89%87&ancestor=list&cmsid=91fe43da94b3ac037ee2da957a90d6f9&cmras=0&cn=0&gn=0&kn=49&crn=0&bxn=20&fsn=129&cuben=0&pornn=0&manun=24&adstar=0&clw=284#id=9f3a1eeb2c9fe66d36e55cf51f4b33ae&currsn=0&ps=101&pc=101","111");
Person p1 = new Person("https://image.so.com/view?q=%E5%9B%BE%E7%89%87&listsrc=sobox&listsign=9f3a1eeb2c9fe66d36e55cf51f4b33ae&src=360pic_new_strong&correct=%E5%9B%BE%E7%89%87&ancestor=list&cmsid=91fe43da94b3ac037ee2da957a90d6f9&cmras=0&cn=0&gn=0&kn=49&crn=0&bxn=20&fsn=129&cuben=0&pornn=0&manun=24&adstar=0&clw=284#id=9f3a1eeb2c9fe66d36e55cf51f4b33ae&currsn=0&ps=101&pc=101","222");
Person p2 = new Person("https://image.so.com/view?q=%E5%9B%BE%E7%89%87&listsrc=sobox&listsign=9f3a1eeb2c9fe66d36e55cf51f4b33ae&src=360pic_new_strong&correct=%E5%9B%BE%E7%89%87&ancestor=list&cmsid=91fe43da94b3ac037ee2da957a90d6f9&cmras=0&cn=0&gn=0&kn=49&crn=0&bxn=20&fsn=129&cuben=0&pornn=0&manun=24&adstar=0&clw=284#id=9f3a1eeb2c9fe66d36e55cf51f4b33ae&currsn=0&ps=101&pc=101","333");
p3.start();
p1.start();
p2.start();
}
}
//下载器
class WebDownLoader{
// 下载方法
public void downloader(String url,String name) throws IOException {
try {
FileUtils.copyURLToFile(new URL(url),new File(name));
} catch (IOException e) {
e.printStackTrace();
System.out.println("IO异常,下载方法出现问题");
}
}
}
实现runnable接口
-
创建线程类实现Runnable接口
-
重写 run()方法,编写线程执行体
-
创建线程对象,调用start()方法启动线程
package com.gentlesoft.oa.archives.controller;
// 创建线程方法2:实现Runnable接口,重写run方法,执行线程需要丢入Runnable接口实现类,调用start方法
public class Person implements Runnable {
@Override
public void run() {
// run()方法线程体
for (int i = 0; i < 10; i++) {
System.out.println("我再看代码===="+i);
}
}
public static void main(String[] args) {
//创建runnable接口的实现类对象
Person person = new Person();
// 创建线程对象,通过线程对象来开启我们的线程
Thread thread = new Thread(person);
thread.start();
for (int i = 0; i < 10; i++) {
System.out.println("我在学习===="+i);
}
}
}
初始并发
package com.gentlesoft.oa.archives.controller;
// 多个线程实现同时操作一个类
// 买火车票的例子
// 发现问题:多个线程操作同一个资源的情况下,线程不安全
public class Person implements Runnable {
// 票数
private int ticktNums = 10;
@Override
public void run() {
while(true){
if (ticktNums<=0){
break;
}
// 模拟延迟
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"---->拿到了第"+ticktNums--+"张票");
}
}
public static void main(String[] args) {
Person person = new Person();
new Thread(person,"小明").start();
new Thread(person,"胡").start();
new Thread(person,"小拜拜").start();
}
}
案例:龟兔赛跑
package com.gentlesoft.oa.archives.controller;
public class Race implements Runnable{
// 胜利者
private static String winner;
@Override
public void run() {
for (int i = 0; i <= 100; i++) {
// 模拟兔子休息
if(Thread.currentThread().getName()=="兔子"){
try {
Thread.sleep(15);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
// 判断比赛是否结束
boolean flag = gameOver(i);
if(flag==true){
// 如果比赛结束 停止程序
break;
}
System.out.println(Thread.currentThread().getName()+"---->跑了"+i+"步");
}
}
// 判断是否完成比赛
private boolean gameOver(int steps){
if(winner!=null){
return true;
}{
if (steps>=100){
winner = Thread.currentThread().getName();
System.out.println("winner is :"+winner);
return true;
}
}
return false;
}
public static void main(String[] args) {
Race race = new Race();
new Thread(race,"兔子").start();
new Thread(race,"乌龟").start();
}
}
实现Callable接口
-
实现Callable接口,需要返回值类型化
-
重写call方法,需要抛出异常
-
创建目标对象
-
创建执行任务:ExecutorService ser = Executors.newFixedThreadPool(1);
-
提交执行:Future<Bollean> result = ser.submit(t1);
-
获取结果:boolean r1= result.get();
-
关闭服务:ser.shutdownNow():
package com.gentlesoft.oa.archives.controller;
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> {
// 联系Thread,实现多线程同步下载图片
private String url;
private String name ;
public TestCallable(String url,String name){
this.url = url;
this.name = name;
}
@Override
public Boolean call() throws IOException {
WebDownLoader webDownLoader = new WebDownLoader();
try {
webDownLoader.downloader(url,name);
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("下载了 图片:"+name);
return true;
}
public static void main(String[] args) throws ExecutionException,InterruptedException {
TestCallable p1 = new TestCallable("https://p1.ssl.qhimg.com/t01e2198cad53ecdf1b.jpg","1.jpg");
TestCallable p2 = new TestCallable("https://p1.ssl.qhimg.com/t01e2198cad53ecdf1b.jpg","2.jpg");
TestCallable p3 = new TestCallable("https://p1.ssl.qhimg.com/t01e2198cad53ecdf1b.jpg","3.jpg");
// 创建执行服务
ExecutorService ser = Executors.newFixedThreadPool(3);
// 提交执行
Future<Boolean> r1 = ser.submit(p1);
Future<Boolean> r2 = ser.submit(p2);
Future<Boolean> r3 = ser.submit(p3);
// 获取结果
boolean rs1 = r1.get();
boolean rs2 = r2.get();
boolean rs3 = r3.get();
System.out.println(rs1);
System.out.println(rs2);
System.out.println(rs3);
// 关闭服务
ser.shutdownNow();
}
}
//下载器
class WebDownLoader{
// 下载方法
public void downloader(String url,String name) throws IOException {
try {
FileUtils.copyURLToFile(new URL(url),new File(name));
} catch (IOException e) {
e.printStackTrace();
System.out.println("IO异常,下载方法出现问题");
}
}
}
静态代理
package com.gentlesoft.oa.archives.controller;
//静态 代理模式
// 真实对象和代理对象都要实现同一个接口
// 代理对象代理真实角色
// 好处:
// 代理对象可以做很多真实对象做不了的事情
// 真实对象专注自己的事情
public class TestCallable {
public static void main(String[] args) {
// 多线程方式
new Thread(()-> System.out.println("我爱你")).start();
You you = new You();
// 代理模式
/*WeddingCompany weddingCompany = new WeddingCompany(you);
weddingCompany.HappyMarry();*/
new WeddingCompany(new You()).HappyMarry();
}
}
interface Marry{
void HappyMarry();
}
// 真实结婚的角色You
class You implements Marry{
@Override
public void HappyMarry() {
System.out.println("我要结婚了,非常开心");
}
}
// 代理角色,辅助结婚
class WeddingCompany implements Marry{
// 代理角色----真实的目标角色
private Marry target;
public WeddingCompany(Marry target) {
this.target = target;
}
@Override
public void HappyMarry() {
before();
this.target.HappyMarry();// 这就是真实对象
after();
}
private void after() {
System.out.println("结婚之后收尾款");
}
private void before(){
System.out.println("结婚之前布置会场");
}
}
Lamda表达式
package com.gentlesoft.oa.archives.controller;
public class TestLamda {
//3.静态内部类
static class Like2 implements ILike{
@Override
public void Lamda() {
System.out.println("i like lamda2");
}
}
public static void main(String[] args) {
ILike like = new Like();
like.Lamda();
like = new Like2();
like.Lamda();
// 4.局部内部类
class Like3 implements ILike{
@Override
public void Lamda() {
System.out.println("i like lamda3");
}
}
like = new Like3();
like.Lamda();
// 5. 匿名内部类
like = new ILike() {
@Override
public void Lamda() {
System.out.println("i like lamda4");
}
};
like.Lamda();
// 6.lamda 表达式简化
like = ()->{
System.out.println("i like lamda5");
};
like.Lamda();
}
}
// 1.定义函数式接口
interface ILike{
void Lamda();
}
//2.实现类
class Like implements ILike{
@Override
public void Lamda() {
System.out.println("i like lamda");
}
}
线程停止
package com.gentlesoft.oa.archives.controller;
// 测试stop
// 1.建议线程正常停止-->利用次数,不建议死循环
// 2.建议使用标志位--->设置一个标志
// 3.不要使用stop/destory等过时或者JDK不建议使用的方法
public class Race implements Runnable{
// 1.设置一个标志
private boolean flag= true;
@Override
public void run() {
int i= 0;
while(flag){
System.out.println("run.....Thread"+i++);
}
}
// 设置一个公开的方法停止线程,转换标志位
public void stop(){
this.flag = false;
}
public static void main(String[] args) {
Race teststop = new Race();
new Thread(teststop).start();
for (int i = 0; i < 1000; i++) {
System.out.println("main主线程:"+i);
if (i==900){
// 调用stop方法让线程停止
teststop.stop();
System.out.println("该线程停止了");
}
}
}
}
线程休眠
package com.gentlesoft.oa.archives.controller;
import java.text.SimpleDateFormat;
import java.util.Date;
// 模拟网络延时:方法问题的发生性
// 模拟倒计时
public class Race {
public static void tenDown() throws InterruptedException {
int num = 10;
while (true) {
Thread.sleep(1000);
System.out.println(num--);
if (num <= 0) {
break;
}
}
}
public static void main(String[] args) throws InterruptedException {
/* try {
tenDown();
} catch (InterruptedException e) {
e.printStackTrace();
}
}*/
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.gentlesoft.oa.archives.controller;
// 测试礼让线程
// 礼让不一定成功,看CPU心情
public class Race {
public static void main(String[] args) {
MyYield myYield = new MyYield();
new Thread(myYield,"a").start();
new Thread(myYield,"b").start();
}
}
class MyYield implements Runnable{
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"线程开始执行");
Thread.yield();// 线程开始礼让
System.out.println(Thread.currentThread().getName()+"线程停止执行");
}
}
线程强制执行join(插队)
package com.gentlesoft.oa.archives.controller;
// 测试join方法
public class Race implements Runnable{
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println("线程vip来了"+i);
}
}
public static void main(String[] args) throws InterruptedException {
// 启动线程
Race race = new Race();
Thread thread = new Thread(race);
thread.start();
// 主线程
for (int i = 0; i < 1000; i++) {
if(i==200){
thread.join();
}
System.out.println("main:"+i);
}
}
}
检测线程的状态
package com.gentlesoft.oa.archives.controller;
// 观测线程状态
public class Race {
public static void main(String[] args) throws InterruptedException {
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);
// 观察启动后
thread.start();
state = thread.getState();
System.out.println(state);
while(state!=Thread.State.TERMINATED){// 只要线程不停止,就一直输出状态
Thread.sleep(1000);
state = thread.getState();// 更新线程状态
System.out.println(state);
}
}
}
线程的优先级--用数字表示
getPriority()
setPriority(int xxx)
package com.gentlesoft.oa.archives.controller;
// 测试线程的优先级
public class Race {
public static void main(String[] args) {
// 主线程的优先级
System.out.println(Thread.currentThread().getName()+"---->"+Thread.currentThread().getPriority());
Mypriority mypriority = new Mypriority();
Thread t1= new Thread(mypriority);
Thread t2= new Thread(mypriority);
Thread t3= new Thread(mypriority);
Thread t4= new Thread(mypriority);
// 设置优先级,在启动
t1.start();
t2.setPriority(1);
t2.start();
t3.setPriority(4);
t3.start();
t4.setPriority(Thread.MAX_PRIORITY);
t4.start();
}
}
class Mypriority implements Runnable{
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"---->"+Thread.currentThread().getPriority());
}
}
守护线程
package com.gentlesoft.oa.archives.controller;
// 测试守护线程
public class Race {
public static void main(String[] args) {
God god = new God();
You you = new You();
Thread thread = new Thread(god);
thread.setDaemon(true);// 默认是false表示用户线程,正常的线程都是用户线程
thread.start();// 上帝守护线程开启
new Thread(you).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("=======googbye world=====");
}
}
线程同步
不安全情况
package com.gentlesoft.oa.archives.controller;
// 不安全的买票
// 线程不安全 有负数
public class Race {
public static void main(String[] args) {
BuyTicket station = new BuyTicket();
new Thread(station,"一号主要人员").start();
new Thread(station,"二号主要人员").start();
new Thread(station,"三号主要人员").start();
}
}
class BuyTicket implements Runnable{
//票
private int ticketNums = 10;
boolean flag = true;//外部停止方式
@Override
public void run() {
// 买票
while(flag){
try {
buy();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
private void buy() throws InterruptedException {
// 判断是否邮票
if(ticketNums<=0){
flag=false;
return;
}
// 模拟延迟
Thread.sleep(100);
// 买票
System.out.println(Thread.currentThread().getName()+"买到"+ticketNums--);
}
}
package com.gentlesoft.oa.archives.controller;
// 不安全的取钱
// 两个人去银行取钱,账户
public class Race {
public static void main(String[] args) {
Account account = new Account(100,"结婚基金");
Drawing you = new Drawing(account,50,"你");
Drawing gilefriend = new Drawing(account,100,"女朋友");
you.start();
gilefriend.start();
}
}
// 账户
class Account{
int money ; //余额
String name;//卡名
public Account(int money, String name) {
this.money = money;
this.name = name;
}
}
// 银行:模拟取钱
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;
this.nowMoney = nowMoney;
}
// 取钱
@Override
public void run() {
if(account.money-drawingMoney<0){
System.out.println(Thread.currentThread().getName()+"账户余额不足");
return;
}
// sleep可以放大问题的发生性
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//卡内余额 = 余额-取的钱
account.money = account.money-drawingMoney;
// 手里的钱
nowMoney = nowMoney + drawingMoney;
System.out.println(account.name+"账户余额为:"+account.money);
System.out.println(account.name+"手里余额为:"+nowMoney);
}
}
同步块
package com.gentlesoft.oa.archives.controller;
// 不安全的买票
// 线程不安全 有负数
public class Race {
public static void main(String[] args) {
BuyTicket station = new BuyTicket();
new Thread(station,"一号主要人员").start();
new Thread(station,"二号主要人员").start();
new Thread(station,"三号主要人员").start();
}
}
class BuyTicket implements Runnable{
//票
private int ticketNums = 10;
boolean flag = true;//外部停止方式
@Override
public void run() {
// 买票
while(flag){
try {
buy();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
// synchronized 同步方法,锁的是this
private synchronized void buy() throws InterruptedException {
// 判断是否邮票
if(ticketNums<=0){
flag=false;
return;
}
// 模拟延迟
Thread.sleep(100);
// 买票
System.out.println(Thread.currentThread().getName()+"买到"+ticketNums--);
}
}
package com.gentlesoft.oa.archives.controller;
// 不安全的取钱
// 两个人去银行取钱,账户
public class Race {
public static void main(String[] args) {
Account account = new Account(100,"结婚基金");
Drawing you = new Drawing(account,50,"你");
Drawing gilefriend = new Drawing(account,100,"女朋友");
you.start();
gilefriend.start();
}
}
// 账户
class Account{
int money ; //余额
String name;//卡名
public Account(int money, String name) {
this.money = money;
this.name = name;
}
}
// 银行:模拟取钱
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;
this.nowMoney = nowMoney;
}
// 取钱
@Override
public void run() {
// 锁的对象就是变化的变量,锁的是增删改
synchronized (account){
if(account.money-drawingMoney<0){
System.out.println(Thread.currentThread().getName()+"账户余额不足");
return;
}
// sleep可以放大问题的发生性
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//卡内余额 = 余额-取的钱
account.money = account.money-drawingMoney;
// 手里的钱
nowMoney = nowMoney + drawingMoney;
System.out.println(account.name+"账户余额为:"+account.money);
System.out.println(account.name+"手里余额为:"+nowMoney);
}
}
}
死锁
package com.gentlesoft.oa.archives.controller;
import org.apache.poi.ss.formula.functions.Mirr;
// 死锁:多个线程互相抱着对方需要的资源,然后形成僵持
public class DeadLock {
public static void main(String[] args) {
Makeup g1 = new Makeup(0,"灰姑娘");
Makeup g2 = new Makeup(1,"白雪公主");
g1.start();
g2.start();
}
}
// 口红
class Lipstick{
}
// 镜子
class Mirror{
}
class Makeup extends Thread{
// 需要的资源只有一份,用static来保证只有一份
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();
}
}
// 化妆,互相持有方的锁,就是需要拿到对方的资源
private 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(锁)
ReentrantLock (可重入锁)实现了Lock
package com.gentlesoft.oa.archives.controller;
import java.util.concurrent.locks.ReentrantLock;
//测试Lock锁
public class TestLock {
public static void main(String[] args) {
TestLock2 testLock2 = new TestLock2();
new Thread(testLock2).start();
new Thread(testLock2).start();
new Thread(testLock2).start();
}
}
class TestLock2 implements Runnable{
int tickNums = 10;
// 定义lock锁
private final ReentrantLock lock = new ReentrantLock();
@Override
public void run() {
while(true){
try {
lock.lock();// 加锁
if(tickNums>0){
System.out.println(tickNums--);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}else{
break;
}
}finally {
// 解锁
lock.unlock();
}
}
}
}
生产者消费者模式(问题)
解决方式1、
package com.gentlesoft.oa.archives.controller;
import java.util.concurrent.locks.ReentrantLock;
// 测试: 生产者消费者模型---> 利用缓冲区解决:管程法
// 生产者、消费者 产品 、 缓冲区
public class TestPC{
public static void main(String[] args) {
SynContainer container = new SynContainer();
new Productor(container).start();
new Customer(container).start();
}
}
// 生产者
class Productor extends Thread{
SynContainer container;
public Productor(SynContainer container){
this.container = container;
}
// 生产
@Override
public void run() {
for (int i = 0; i < 100; i++) {
container.push(new Chicken(i));
System.out.println("生产了:"+i+"鸡");
}
}
}
// 消费者
class Customer extends Thread{
SynContainer container;
public Customer(SynContainer container){
this.container = container;
}
// 消费
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println("消费了===》"+container.pop().id+"鸡");
}
}
}
// 产品
class Chicken{
int id; // 产品编号
public 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){
// 通知消费者消费,生产等待
}
// 没有满,需要丢入产品
chickens[count] = chicken;
count++;
// 可以通知消费者消费了
}
// 消费者消费产品
public synchronized Chicken pop(){
// 判断能否此消费
if(count==0){
// 等待生产者生产,消费者消费
}
// 如果可以消费
count--;
Chicken chicken = chickens[count];
// 吃完了 , 通知生产者生产
return chicken;
}
}
package com.gentlesoft.oa.archives.controller;
import org.apache.poi.ss.formula.functions.T;
//测试生产者消费者问题2:信号灯法,标志位解决
public class TestPC2 {
public static void main(String[] args) {
TV tv = new TV();
new Player(tv).start();
new Watcher(tv).start();
}
}
// 生产者--》演员
class Player extends Thread{
TV tv;
public Player(TV tv) {
this.tv = tv;
}
@Override
public void run() {
for (int i = 0; i < 20; i++) {
if(i%2==0){
this.tv.play("快了大本营播放中");
}else{
this.tv.play("抖音,记录美好生活");
}
}
}
}
// 消费者
class Watcher extends Thread{
TV tv;
public Watcher(TV tv) {
this.tv = tv;
}
@Override
public void run() {
for (int i = 0; i < 20; i++) {
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.gentlesoft.oa.archives.controller;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
// 测试线程池
public class TestPC2 {
public static void main(String[] args) {
// 1.创建服务,创建线程池
// newFixedThreadPool 参数为:
ExecutorService service = Executors.newFixedThreadPool(10);
// 执行
service.execute(new MyThread());
service.execute(new MyThread());
service.execute(new MyThread());
service.execute(new MyThread());
// 2. 关闭链接
service.shutdown();
}
}
class MyThread implements Runnable{
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
}
}
浙公网安备 33010602011771号