目录









演示:多线程的交替执行
- package JavaSE;
- //创建线程方式一:继承Thread类,重写run()方法,调用start开启线程
- 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线程,主线程
-
- //创建一个线程对象,调用start方法开启线程
- TestThread testThread = new TestThread();
- testThread.start();
-
- for (int i = 0; i < 20; i++) {
- System.out.println("我在学习多线程---"+i);
-
- }
- }
- }
-

结论
线程不一定立即执行,CPU安排调度
演示:实现Runnable接口
- package JavaSE;
- //创建线程方式一:实现Runnable接口,重写run()方法,执行线程需要丢入runnable接口实现类,调用start方法。
- public class TestThread implements Runnable {
- @Override
- public void run() {
- //run方法线程体
- for (int i = 0; i < 200; i++) {
- System.out.println("我在看代码---"+i);
- }
- }
-
- public static void main(String[] args) {
- //main线程,主线程
- //创建runnable接口的实现类对象
- TestThread testThread = new TestThread();
- //创建线程对象,通过线程对象来开启我们的线程,代理
- Thread thread = new Thread(testThread);
- thread.start();
-
- //可合并为一句代码
- //new Thread(testThread).start();
-
- for (int i = 0; i < 200; i++) {
- System.out.println("我在学习多线程---"+i);
- }
- }
- }

演示:多个线程同时操作同一个对象
- package JavaSE;
- //多个线程同时操作同一个对象
- //买火车票的例子
- public class TestThread1 implements Runnable {
-
- //票数
- private int ticketNums = 10;
-
- @Override
- public void run() {
- while(true){
-
- if(ticketNums<=0){
- break;
- }
- //模拟延时
- try {
- Thread.sleep(200);
- } catch (InterruptedException e) {
- throw new RuntimeException(e);
- }
- System.out.println(Thread.currentThread().getName()+"-->拿到了第"+ticketNums--+"张票");
- }
- }
-
- public static void main(String[] args) {
- TestThread1 ticket = new TestThread1();
-
- new Thread(ticket,"小明").start();
- new Thread(ticket,"老师").start();
- new Thread(ticket,"黄牛党").start();
- }
- }

发现问题
多个线程操作同一个资源的情况下,线程不安全,数据紊乱。
1.首先来个赛道距离,然后要离终点越来越近
2.判断比赛是否结束
3.打印出胜利者
4.龟兔赛跑开始
5.故事中是乌龟赢的,兔子需要睡觉,所以我们需要模拟兔子睡觉
6.最终,乌龟赢得了比赛

演示
- package JavaSE;
- //模拟龟兔赛跑
- public class Race implements Runnable{
-
- //胜利者
- private String winner;
-
- @Override
- public void run() {
- for (int i = 0; i <= 100; i++) {
-
- //模拟兔子休息
- if (Thread.currentThread().getName().equals("兔子")&& i%10==0){
- try {
- Thread.sleep(1);
- } catch (InterruptedException e) {
- throw new RuntimeException(e);
- }
- }
- //判断比赛是否结束
- boolean flag = gameOver(i);
- //如果比赛结束了,就停止程序
- if(flag){
- 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();
- }
- }


演示:实现静态代理对比Thread
- package JavaSE;
-
- //静态代理总结:
- //真实对象和代理对象都要实现同一个接口
- //代理对象要代理真实角色
- //婚庆公司==Thread()
- //You()==要调用线程的对象,调用的方法及run()在这里就是labmda表达式实现的方法
-
- //好处:
- //代理对象可以做很多真实对象做不了的事情
- //真实对象就专注做自己的事情
- public class StaticProxy {
- public static void main(String[] args) {
- You you = new You();
- new Thread( () -> System.out.println("我爱你")).start();
-
- new WeddingCompany(new You()).HappyMarry();
-
- /** 可简化为上面一行
- WeddingCompany weddingCompany = new WeddingCompany(new You());
- weddingCompany.HappyMarry();
- */
-
- }
- }
-
- interface Marry{
- void HappyMarry();
- }
-
- //真实角色,你去结婚
- 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("结婚之前,布置现场");
- }
- }




演示1:lambda表达式的推导
- package JavaSE;
- //推导lambda表达式
- public class TestLambda {
-
- //3.静态内部类
- static class Like1 implements ILike{
- @Override
- public void lambda() {
- System.out.println("i like lambda1");
- }
- }
-
- public static void main(String[] args) {
- ILike like = new Like();
- like.lambda();
-
- like = new Like1();
- like.lambda();
-
- //4.局部内部类
- class Like2 implements ILike{
- @Override
- public void lambda() {
- System.out.println("i like lambda2");
- }
- }
-
- like = new Like2();
- like.lambda();
-
- //5.匿名内部类,没有类的名称,必须借助接口或者父类
- like = new ILike(){
- @Override
- public void lambda() {
- System.out.println("i like lambda3");
- }
- };
- like.lambda();
-
- //6.用lambda简化
- like = ()->{
- System.out.println("i like lambda4");
- };
- like.lambda();
-
- }
- }
-
- //1.定义一个函数式接口
- interface ILike{
- void lambda();
- }
-
- //2.实现类
- class Like implements ILike{
- @Override
- public void lambda() {
- System.out.println("i like lambda");
- }
- }

演示2:lambda表达式的简化
- package JavaSE;
-
- public class TestLambda1 {
- public static void main(String[] args) {
-
- ILove love = null;
- /* //1.lambda表达简化
- ILove love =(int a)-> {
- System.out.println("I love you-->"+a);
- };
- //简化1.参数类型
- love = (a)-> {
- System.out.println("I love you-->"+a);
- };
- //简化2.简化括号
- love = a->{
- System.out.println("I love you-->"+a);
- };*/
-
- //简化3.去掉花括号
- love = a-> System.out.println("I love you-->"+a);
-
- love.love(521);
-
- }
- }
-
- //实现类
- interface ILove{
- void love(int a);
- }

总结




演示
- //测试stop
-
- //1.建议线程正常停止--->利用次数,不建议死循环
-
- //2.建议使用标志位--->设置一个标志位
-
- //3.不要使用stop或者destroy等过时或者JDK不建议使用的方法
-
- package JavaSE;
-
- public class TestStop implements Runnable{
- //1.设置一个标志位
- private boolean flag = true;
- @Override
-
- public void run(){
-
- int i =0;
-
- while(flag){
-
- System.out.println("run...Thread"+i++);
- }
- }
-
- //2.设置一个公开的方法停止线程,转换标志位
- public void stop(){
- this.flag = false;
- }
- public static void main(String []args){
-
- TestStop testStop = new TestStop();
- 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 JavaSE;
- import java.text.SimpleDateFormat;
- import java.util.Date;
-
- public class TestSleep2{
-
- /* //倒计时
- Public static void main(String[] args){
- try{
- tenDown();
- }catch(InterruptedException e){
- E.printStackTrace();
- }
- }
- */
-
- public static void main(String[] args){
- //打印当前系统时间
- Date startTime = new Date(System.currentTimeMillis());//获取系统当前时间
-
- while(true){
- try{
- Thread.sleep(1000);
- System.out.println(new SimpleDateFormat("HH:mm:ss").format(startTime));
- startTime = new Date(System.currentTimeMillis());//更新当前时间
- }catch(InterruptedException e){
- e.printStackTrace();
- }
- }
- }
- //模拟倒计时
-
- public void tenDown() throws InterruptedException{
- int num = 10;
- while(true){
- Thread.sleep(1000);
- System.out.println(num--);
- if(num<=0){
- break;
- }
- }
- }
- }
-

演示:测试礼让线程
- //礼让不一定成功!看CPU心情
- public class TestYield{
-
- 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方法,想象为插队
- public class TestJoin implements Runnable{
-
- @Override
- public void run(){
- for(int i = 0;i<100;i++){
- System.out.println("VIP来了"+i);
- }
- }
-
- public static void main(String[] args){
- //启动我们的线程
- TestJoin testJoin = new TestJoin();
- Thread thread = new Thread(testJoin);
- thread.start();
-
- //主线程
- for(int i = 0;i<1000,i++){
- if(i==200){
- thread.join();//插队
- }
- System.out.println("main"+i);
- }
-
- }
- }

Thread.State
线程状态,线程可以处于以下状态之一:
NEW
尚未启动的线程处于此状态
RUNNABLE
在Java虚拟机中执行的线程处于此状态
BLOCKED
被阻塞等待监视器锁定的线程处于此状态
WAITING
正在等待另一个线程执行特定动作的线程处于此状态
TIMED_WAITING
正在等待另一个线程执行动作达到指定等待时间的线程处于此状态
TERMINATED
已退出的线程处于此状态
一个线程可以在给定时间点处于一个状态。这些状态是不反映任何操作系统线程状态的虚拟机状态。
演示:观察测试线程的状态
- 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){//只要线程不终止,就一直输出状态
- Thread.sleep(100);
- state = thread.getState();//更新线程状态
- System.out.println(state);//输出状态
- }
- }
-
- }


演示:测试线程的优先级
- package JavaSE;
-
- //测试线程的优先级
- public class TestPriority {
- public static void main(String[] args) {
- //主线程默认优先级
- System.out.println(Thread.currentThread().getName()+"-->"+Thread.currentThread().getPriority());
-
- MyPriority myPriority = new MyPriority();
-
- Thread t0 = new Thread(myPriority);
- Thread t1 = new Thread(myPriority);
- Thread t2 = new Thread(myPriority);
- Thread t3 = new Thread(myPriority);
- Thread t4 = new Thread(myPriority);
- Thread t5 = new Thread(myPriority);
-
- //先设置优先级再启动
- t0.setPriority(Thread.MAX_PRIORITY);
- t0.start();
-
- t1.setPriority(Thread.MIN_PRIORITY);
- t1.start();
-
- t2.setPriority(4);
- t2.start();
-
- t3.setPriority(Thread.MAX_PRIORITY);//Thread.MAX_PRIORITY = 10
- t3.start();
-
- t4.setPriority(Thread.MIN_PRIORITY);//Thread.MIN_PRIORITY = 1
- t4.start();
-
- t5.setPriority(Thread.NORM_PRIORITY);//Thread.NORM_PRIORITY = 5
- t5.start();
-
- }
- }
-
- class MyPriority implements Runnable{
- @Override
- public void run() {
- System.out.println(Thread.currentThread().getName()+"-->"+Thread.currentThread().getPriority());
- }
- }

演示:人生不过三万天
- package JavaSE;
-
- //测试守护线程
- //上帝守护你
- public class TestDaemon {
- public static void main(String[] args) {
- God god = new God();
- You1 you1 = new You1();
-
- Thread thread = new Thread(god);
- thread.setDaemon(true);//默认是false表示是用户线程,正常的用户线程都是用户线程
- thread.start();//上帝守护线程启动
-
- new Thread(you1).start();//你 用户线程启动
- }
- }
-
- //上帝
- class God implements Runnable{
- @Override
- public void run() {
- while (true){
- System.out.println("上帝保佑着你");
- }
- }
- }
-
- //你
- class You1 implements Runnable{
- @Override
- public void run() {
- for (int i = 0; i < 36500; i++) {
- System.out.println("你一生都开心的活着");
- }
- System.out.println("-=======goodbye!world!========");
-
- }
- }



演示1:不安全的买票
- import com.sun.org.apache.xpath.internal.SourceTree;
-
- //不安全的买票
- public class UnsafeBuyTicket {
-
- 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--);
- }
-
- }
结论
线程不安全,有负数
演示2:不安全的取钱
- //不安全的取钱
- //两个人去银行取钱,账户
- public class UnsafeBank {
- public static void main(String[] args){
- //账户
- Account account = new Account(100,"结婚基金");
-
- Drawing you = new Drawing(account,50,"你");
- Drawing girlFriend = new Drawing(account,100,"girlFriend");
-
- you.start();
- girlFriend.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 drawdingMoney;
-
- //现在手里有多少钱
- int nowMoney;
-
- public Drawing (Account account,int drawdingMoney,String name){
- super(name);
- this.account = account;
- this.drawdingMoney = drawdingMoney;
- }
-
- //取钱
- @Override
- public void run() {
- //判断有没有钱
- if(account.money-drawdingMoney<0){
- System.out.println(Thread.currentThread().getName()+"钱不够,取不了!");
- return;
- }
-
- try{
- Thread.sleep(1000);
- }catch(InterruptedException e){
- e.printStackTrace();
- }
-
- //卡内余额 = 余额-你取的钱
- account.money = account.money - drawdingMoney;
- //你手里的钱
- nowMoney = nowMoney + drawdingMoney;
-
- System.out.println(account.name+"余额为:"+account.money);
- //Thread.currentThread().getName()=this.getName()
- System.out.println(this.getName()+"手里的钱:"+nowMoney);
- }
- }
演示3:线程不安全的集合
- import java.util.ArrayList;
- import java.util.List;
-
-
- //线程不安全的集合
- public class UnsafeList {
- public static void main(String[] args){
- List
list = new ArrayList(); - for(int i= 0;i<10000;i++){
- new Thread(()->{
- list.add(Thread.currentThread().getName());
- }).start();
- }
- System.out.println(list.size());
- }
- }
-
演示1:安全的买票
- import com.sun.org.apache.xpath.internal.SourceTree;
-
- //安全的买票
- public class UnsafeBuyTicket {
-
- 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{
-
- //模拟延时
- Thread.sleep(100);
-
- buy();
- }catch(InterruptedException e){
- e.printStackTrace();
- }
- }
- }
-
- //synchronized 同步方法,锁的是this
- private synchronized void buy() throws InterruptedException{
- //判断是否有票
- if(ticketNums<=0){
- flag = false;
- return;
- }
-
- //买票
- System.out.println(Thread.currentThread().getName()+"拿到"+ticketNums--);
- }
-
-
- }
演示2:安全的取钱
- //安全的取钱
- //两个人去银行取钱,账户
- public class UnsafeBank {
- public static void main(String[] args){
- //账户
- Account account = new Account(100,"结婚基金");
-
- Drawing you = new Drawing(account,50,"你");
- Drawing girlFriend = new Drawing(account,100,"girlFriend");
-
- you.start();
- girlFriend.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 drawdingMoney;
-
- //现在手里有多少钱
- int nowMoney;
-
- public Drawing (Account account,int drawdingMoney,String name){
- super(name);
- this.account = account;
- this.drawdingMoney = drawdingMoney;
- }
-
- //取钱
- //synchronized 默认锁的是this
- @Override
- public void run() {
-
- synchronized(account){
- //判断有没有钱
- if(account.money-drawdingMoney<0){
- System.out.println(Thread.currentThread().getName()+"钱不够,取不了!");
- return;
- }
-
- try{
- Thread.sleep(1000);
- }catch(InterruptedException e){
- e.printStackTrace();
- }
-
- //卡内余额 = 余额-你取的钱
- account.money = account.money - drawdingMoney;
- //你手里的钱
- nowMoney = nowMoney +drawdingMoney;
-
- System.out.println(account.name+"余额为:"+account.money);
- //Thread.currentThread().getName()=this.getName()
- System.out.println(this.getName()+"手里的钱:"+nowMoney);
- }
- }
- }
演示3:线程安全的集合
- import java.util.ArrayList;
- import java.util.List;
-
-
- //线程不安全的集合
- public class UnsafeList {
- public static void main(String[] args){
- List
list = new ArrayList(); - for(int i= 0;i<10000;i++){
- new Thread(()->{
- synchronized(list){
- list.add(Thread.currentThread().getName());
- }
- }).start();
- }
- System.out.println(list.size());
- }
- }
演示:死锁
- import java.awt.Choice;
-
- //死锁:多个线程互相抱着对方需要的资源,然后形成僵持
- public class DeadLock {
- public static void main(String[] args){
- Makeup girl1 = new Makeup(0, "灰姑娘");
- Makeup girl2 = new Makeup(1, "白雪公主");
-
- girl1.start();
- girl2.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+"获得口红的锁");
- }
- }
- }
- }
从JDK5.0开始,Java提供了更强大的线程同步机制—通过显式定义同步锁对象实现同步。同步锁使用Lock对象充当
java.util.concurrent.locks.Lock接口是控制多个线程对共享资源进行访问的工具。锁提供了对共享资源的独占访问,每次只能有一个线程对Lock对象加锁,线程开始访问共享资源之前应先获得Lock对象
ReentrantLock类实现了Lock,它拥有与synchronized相同的并发性和内存语义,在实现线程安全的控制中,比较常用的是ReentrantLock,可以显示加锁、释放锁
用法:
- class A{
-
- //定义lock锁
- private final ReentrantLock lock = new ReentrantLock();
-
- public void m(){
- lock.lock();//加锁
- try{
- //保证线程安全的代码
- }
- finally{
- lock.unlock();
- //如果同步代码有异常,要将unlock()写入finally语句块
- }
- }
- }
演示:lock
- import java.util.concurrent.locks.ReentrantLock;
-
- 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 ticketNum = 10;
-
- //定义lock锁
- private final ReentrantLock lock = new ReentrantLock();
-
- @Override
- public void run(){
- while(true){
- try{
- lock.lock();//加锁
- if(ticketNum>0){
- try{
- Thread.sleep(1000);
- }catch(InterruptedException e){
- e.printStackTrace();
- }
- System.out.println(ticketNum--);
- }else{
- break;
- }
- }finally{
- //解锁
- lock.unlock();
- }
- }
- }
- }
synchronized与Lock的对比
这是一个线程同步问题,生产者和消费者共享同一个资源,并且生产者和消费者之间相互依赖,互为条件
注意:均是Object类的方法,都只能在同步方法或者同步块代码块中使用,否则会抛出异常lllegalMonitorStateException
解决方式1
并发协作模型“生产者/消费者模式”--->管程法
生产者将生产好的数据放入缓冲区,消费者从缓冲区拿出数据
解决方式2
演示:信号灯法
- package JavaSE;
-
- //演示:录制节目,演员录制,观众等待
- public class TestPc {
- public static void main(String[] args) {
- TV tv = new TV();
- new Actor(tv).start();
- new Watcher(tv).start();
- }
- }
-
- //生产者-->演员
- class Actor extends Thread{
- TV tv;
-
- public Actor(TV tv) {
- this.tv = tv;
- }
-
- @Override
- public void run() {
- for (int i = 0; i < 20; i++) {
- if(i%2==0){
- this.tv.act("快乐大本营");
- }else {
- this.tv.act("抖音:记录美好生活");
- }
- }
- }
- }
-
- //消费者-->观众
- 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{
- //演员表演,观众等待 T
- //观众观看,演员等待 F
- String voice;//表演的节目
- boolean flag = true;
-
- //演员表演
- public synchronized void act(String voice){
- if(!flag){
- try {
- this.wait();
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
-
- System.out.println("演员表演了:"+voice);
- //通知观众观看
- this.notify();//通知唤醒
- 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 JavaSE;
-
- import java.util.concurrent.ExecutorService;
- import java.util.concurrent.Executors;
-
- //测试线程池
- public class TestPool {
-
- 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());
- }
- }