万字简单总结一下Java学习过程中的多线程,有不足之处欢迎指正,觉得不错的也可以三连一下
继承Thread类
创建线程方式1:继承Thread类,重写run()方法,调用start开启线程
注意:线程开启不一定立即执行,由CPU调度执行
总结
public class TestThread1 extends Thread{ public void run(){ //run方法线程体 for(int i = 0;i < 200; i++){ System.out.println("我在看代码---"+i); } } public static void main(String[] args) { //main线程, 主线程 //创建一个线程对象 TestThread1 testThread1 = new TestThread1(); //调用start()方法开启线程 testThread1.start(); for(int i = 0;i < 1000;i++){ System.out.println("我在看书---"+i); } } }
public class TestThread extends Thread{ private String url;//网络图片地址 private String name;//保存的文件名 public TestThread(String url,String name){ this.url = url; this.name = name; } //下载图片线程的执行体 public void run(){ WebDownloader webDownloader = new WebDownloader(); webDownloader.downloader(url,name); System.out.println("下载了文件名为:"+name); } public static void main(String[] args) { TestThread t1 = new TestThread("","1.jpg"); TestThread t2 = new TestThread("","2.jpg"); TestThread t3 = new TestThread("","3.jpg"); t1.start(); t2.start(); t3.start(); } } //下载器 class WebDownloader{ //下载方法 public void downloader(String url,String name){ try { FileUtils.copyURLToFile((new URL(url)), new File(name)); }catch (IOException e){ e.printStackTrace(); System.out.println("IO异常,Downloader方法出现问题“); } } }
实现Runable接口:声明实现类Runnable接口。 那个类然后实现了run方法。 然后可以分配类的实例,在创建Thread时作为参数传递,并启动。
创建线程方式2:
创建线程方式2:实现runnable接口,重写run()方法,执行线程需要丢入Thread对象中
总结
实现接口Runable具有多线程能力
启动线程:传入目标对象+Thread对象.start()
推荐使用:避免了单继承的局限性,灵活方便,方便同一个对象被多个线程使用
public class TestThread1 implements Runnable{ public void run(){ //run方法线程体 for(int i = 0;i < 200; i++){ System.out.println("我在看代码---"+i); } } public static void main(String[] args) { //创建runnable接口的实现类对象 TestThread1 testThread1 = new TestThread1(); //创建线程对象,通过线程对象来开启我们的线程 new Thread(testThread1).start(); for(int i = 0;i < 1000;i++){ System.out.println("我在看书---"+i); } } }
public class TestThread implements Runnable{ private String url;//网络图片地址 private String name;//保存的文件名 public TestThread(String url,String name){ this.url = url; this.name = name; } //下载图片线程的执行体 public void run(){ WebDownloader webDownloader = new WebDownloader(); webDownloader.downloader(url,name); System.out.println("下载了文件名为:"+name); } public static void main(String[] args) { TestThread t1 = new TestThread("","1.jpg"); TestThread t2 = new TestThread("","2.jpg"); TestThread t3 = new TestThread("","3.jpg"); new Thread(t1).start(); new Thread(t2).start(); new Thread(t3).start(); } } //下载器 class WebDownloader{ //下载方法 public void downloader(String url,String name){ try { FileUtils.copyURLToFile((new URL(url)), new File(name)); }catch (IOException e){ e.printStackTrace(); System.out.println("IO异常,Downloader方法出现问题“); } } }
//模拟龟兔赛跑 public class Race implements Runnable { //胜利者 private static String winner; @Override public void run(){ for (int i = 0; i <= 100; i++) { //模拟兔子休息 if (Thread.currentThread().getName().equals("兔子") && i % 10 == 0) { try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } } //判断比赛是否结束 boolean flag = gameover(i); //如果比赛结束,就停止程序 if (flag) { break; } System.out.println(Thread.currentThread().getName() + "-->跑了" + i + "步"); } } //判断是否完成比赛 private boolean gameover(int steps) { //判断是否有胜利者 if (winner != null) {//winner不为null,则说明存在胜利者 return true; } else { 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(); } }
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() { WebDownloader webDownloader = new WebDownloader(); //传入方法 webDownloader.downloader(url, name); System.out.println("下载的文件名为" + name); return true; } public static void main(String[] args) throws Exception { TestCallable t1 = new TestCallable("http://b-ssl.duitang.com/uploads/item/201704/21/20170421083329_3cxt8.png", "1.png"); TestCallable t2 = new TestCallable("https://i02piccdn.sogoucdn.com/7e1dad42a62db2df", "2.png"); TestCallable t3 = new TestCallable("https://i01piccdn.sogoucdn.com/f13b319fd77655ec", "3.png"); //创建执行服务: ExecutorService ser = Executors.newFixedThreadPool(3); //提交执行: Future<Boolean> r1 = ser.submit(t1); Future<Boolean> r2 = ser.submit(t2); Future<Boolean> r3 = ser.submit(t3); //获取结果: boolean rs1 = r1.get(); boolean rs2 = r2.get(); boolean rs3 = r3.get(); //关闭服务: ser.shutdownNow(); } } //下载器 class WebDownloader { //下载---方法 public void downloader(String url, String name) { try { FileUtils.copyURLToFile(new URL(url), new File(name)); } catch (IOException e) { e.printStackTrace(); System.out.println("IO异常,down的方法出现问题!"); } } }
概念
好处
public class StaticProxy { public static void main(String[] args) { You you=new You(); WeddingCompany weddingCompany=new WeddingCompany(you); //等价于new WeedingCompany(new you()) weddingCompany.HappyMarry(); } } //功能接口 interface Marry{ void HappyMarry(); } //实现Marry的接口 //真实角色 class You implements Marry{ @Override public void HappyMarry() { System.out.println("你要结婚了吗?,看起来超开心的"); } } //实现Marry的接口 //代理角色-婚庆公司 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 before(){ System.out.println("结婚之前,布置现场"); } private void after(){ System.out.println("结婚之后,收尾款"); } }
public interface Runnable{ public abstract void run(); }
//推导Lambda表达式 public class TestLambda01 { //3.静态外部类(需要加static) static class Like2 implements ILike { @Override public void lambda() { System.out.println("I Like lamdbda2"); } } //定义好接口和实现类(实现接口)之后,写main方法 public static void main(String[] args) { //函数式接口名称+自定义变量=new+实现类(实现接口)变量Like ILike like=new Like(); like.lambda(); //静态内部类 //自定义变量名=new +实现类(实现接口)变量Like2 like=new Like2(); like.lambda(); //4.局部内部类 class Like3 implements ILike { @Override public void lambda() { System.out.println("I Like lamdbda3"); } } like=new Like3(); like.lambda(); //5.匿名内部类,没有类的名称,必须借助接口或者父类 like = new ILike() { @Override public void lambda() { System.out.println("I Like lamdbda4"); } }; like.lambda(); //6.用lambda接简化 like=()-> { System.out.println("I Like lamdbda5"); }; like.lambda(); } } //1.定义一个函数式接口 interface ILike{ void lambda(); } //2.实现类(实现接口) //implements class Like implements ILike { @Override public void lambda() { System.out.println("I Like lamdbda1"); } }
public class TestLambda02 { 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,b)->{ System.out.println("I Love You-->"+a+"-->"+b); }; love.love(521,520); //简化3.去掉花括号 love=(a,b)-> System.out.println("I Love You-->"+a+"-->"+b); love.love(521,520); } } //函数式式接口 interface ILove{ void love(int a,int b); }
方法 | 说明 |
---|---|
setPriority(int newPriority) | 更改线程的优先级 |
static void sleep(long millis) | 在指定的毫秒数内让当前正在执行的线程休眠 |
void join() | 等待该线程终止 |
static void yield | 暂停当前正在执行的线程对象,并执行其他线程 |
void interrupt() | 中断线程,别用这个方式 |
boolean isAlive() | 测试线程是否处于活动状态 |
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("线程已到900,停止"); } } } }
public class TestSleep implements Runnable{ //票数 private int ticketNums = 10; @Override public void run() { while(true) { if(ticketNums<=0) { break; } //模拟延时 try { Thread.sleep(200); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+"-->拿到了第"+ticketNums--+"票"); } } public static void main(String[] args) { TestSleep ticket=new TestSleep(); //随机输出 new Thread(ticket,"小明").start(); new Thread(ticket,"老师").start(); new Thread(ticket,"黄牛党").start(); } }
//模拟倒计时 public class TestSleep02 { public static void main(String[] args) { //模拟倒计时 //tenDown(); //打印当前系统时间 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 static void tenDown(){ int num=10; while(true){ try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(num--); if(num<=0) { break; } } } }
//测试礼让线程 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){ try { thread.join();//插队 } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println("main"+i); } } }
//观察测试线程的状态 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("123123"); }); //观察状态 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); } catch (InterruptedException e) { e.printStackTrace(); } state= thread.getState();//更新线程状态 System.out.println(state);//输出状态 } } }
//测试守护线程 public class TestDaemon { public static void main(String[] args) { God god=new God(); You you=new You(); Thread thread=new Thread(god); thread.setDaemon(true); //启动守护线程 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("=======goodbye world!======="); } }
并发:同一个对象被多个线程同时操作
处理多线程问题时,多个线程访问同一个对象,并且某些线程还想修改这个对象,这时候我们就需要线程同步,线程同步其实就是一个等待机制,多个需要同时访问此对象的线程进入这个对象的等待池形成队列,等待前面线程使用完毕,下一个线程再使用.
线程同步形成条件:队列+锁
线程同步存在的缺陷
//不安全购票 //线程不安全,有0和负数输出 public class UnsafeBuyTicket { public static void main(String[] args) { BuyTicket station=new BuyTicket(); new Thread( station,"花花001").start(); new Thread( station,"花花002").start(); new Thread( station,"花花003").start(); } } //需要一个购票方法(是一个多线程) class BuyTicket implements Runnable{ //需要票数 private int ticketNums=10; boolean flag=true;//外部停止方式 @Override public void run() { while (flag){ buy(); } } //创建买票方法 private void buy(){ //判断是否有票 if (ticketNums<=0) { flag=false; return; } try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } //买票 System.out.println(Thread.currentThread().getName()+"拿到"+ticketNums--); } }
//不安全取钱 //需要两个人去银行取钱-->需要账户 public class UnsafeBank { public static void main(String[] args) { //账户 Account account=new Account(100,"结婚资金"); Drawing you=new Drawing(account,50,"你"); Drawing yougirlfriend=new Drawing(account,100,"yougirlfriend"); you.start(); yougirlfriend.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; } @Override //取钱 public void run() { if(account.money-drawingMoney<0){//判断账户是否有余额 System.out.println(Thread.currentThread().getName()+"余额不足!"); return; } try { Thread.sleep(1000); //sleep放大问题的发生性 } catch (InterruptedException e) { e.printStackTrace(); } account.money= account.money-drawingMoney;//卡内余额=余额-你取的钱 nowMoney=nowMoney+drawingMoney; //你手里的钱 System.out.println(Thread.currentThread().getName()+"手里的钱:"+nowMoney); System.out.println(account.name+"余额为:"+account.money); //这里this.getName()等价于Thread.currentThread().getName() } }
//线程不安全的集合 public class UnsafeList { public static void main(String[] args) { List<String> list=new ArrayList<>(); for (int i = 0; i < 10000; i++) { new Thread(()->{ list.add(Thread.currentThread().getName()); }).start(); } try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(list.size()); } }
public synchronizeed void method(int args){}
synchronized(Obj){}
Obj称之为同步监视器
同步监视器的执行过程
第一个线程访问,锁定同步监视器,执行其中的代码
第二个线程访问,发现同步监视器被锁定,无法访问
第一个线程访问完毕,解锁同步监视器
第二个线程访问,发现同步监视器没有锁,然后锁定并访问
运用同步解决三大不安全案例
案例一
//不安全购票 //线程不安全,有0和负数输出 public class UnsafeBuyTicket { public static void main(String[] args) { BuyTicket station=new BuyTicket(); new Thread( station,"花花001").start(); new Thread( station,"花花002").start(); new Thread( station,"花花003").start(); } } //需要一个购票方法(是一个多线程) class BuyTicket implements Runnable{ //需要票数 private int ticketNums=10; boolean flag=true;//外部停止方式 @Override public void run() { while (flag){ buy(); } } //创建买票方法 //synchronized 同步方法,锁的是this(BuyTicket) private synchronized void buy(){ //判断是否有票 if (ticketNums<=0) { flag=false; return; } try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } //买票 System.out.println(Thread.currentThread().getName()+"拿到"+ticketNums--); } }
//不安全取钱 //需要两个人去银行取钱-->需要账户 public class UnsafeBank { public static void main(String[] args) { //账户 Account account=new Account(100,"结婚资金"); Drawing you=new Drawing(account,50,"你"); Drawing yougirlfriend=new Drawing(account,100,"yougirlfriend"); you.start(); yougirlfriend.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; } @Override //取钱 // synchronized 默认的锁是this. //锁的对象就是变化的量,即需要增删改的量 public void run() { synchronized(account){ if(account.money-drawingMoney<0){//判断账户是否有余额 System.out.println(Thread.currentThread().getName()+"无法取钱,余额不足!"); return; } try { Thread.sleep(1000); //sleep放大问题的发生性 } catch (InterruptedException e) { e.printStackTrace(); } account.money= account.money-drawingMoney;//卡内余额=余额-你取的钱 nowMoney=nowMoney+drawingMoney; //你手里的钱 System.out.println(Thread.currentThread().getName()+"手里的钱:"+nowMoney); System.out.println(account.name+"余额为:"+account.money); //这里this.getName()等价于Thread.currentThread().getName() } } }
//线程不安全的集合 public class UnsafeList { public static void main(String[] args) { List<String> list=new ArrayList<>(); for (int i = 0; i < 10000; i++) { new Thread(()->{ synchronized (list){ list.add(Thread.currentThread().getName()); } }).start(); } try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(list.size()); } }
//测试JUC安全类型的集合 public class TestJUC { public static void main(String[] args) { CopyOnWriteArrayList<String> list=new CopyOnWriteArrayList<String>(); for (int i = 0; i < 10000; i++) { new Thread(()->{ list.add(Thread.currentThread().getName()); }).start(); } try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(list.size()); } }
package thread; //死锁,多个线程互相抱着对方需要的资源,然后形成僵持. 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 lipstic=new Lipstick(); static Mirror mirror=new Mirror(); int choice; //选择 String girlname;//使用化妆品的人 //使用构造器 Makeup(int choice,String girlname){ this.choice=choice; this.girlname=girlname; } //继承Thread类型 就需要重写run方法 @Override public void run() { try { makeup(); } catch (Exception e) { e.printStackTrace(); } //化妆 } //化妆,互相持有对方的锁,需要拿到对方的资源 private void makeup(){ if(choice==0) { synchronized (lipstic){//获得口红的锁 System.out.println(this.girlname+"获得口红的锁"); try { Thread.sleep(1000); } catch (Exception e) { e.printStackTrace(); } } //解决死锁的方法将下边的synchronized (mirror)拿出if语句即可 synchronized (mirror){//一秒钟后想获得镜子 System.out.println(this.girlname+"获得镜子的锁"); } }else{ synchronized (mirror) {//获得镜子的锁 System.out.println(this.girlname + "获得镜子的锁"); try { Thread.sleep(2000); } catch (Exception e) { e.printStackTrace(); } } //解决死锁的方法将下边的synchronized (lipstic)拿出else语句即可 synchronized (lipstic) {//一秒钟后想获得口红 System.out.println(this.girlname + "获得口红的锁"); } } } }
//语法 class A{ private final ReentrantLock lock=new ReentrantLock(); public void mainone(){ try{ lock.lock(); //保证线程安全的代码 }finally { lock.unlock(); //如果finally同步代码有异常,要将unlock()写入语句块 } } }
//测试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 ticketNums=10; //定义Lock锁(可重入锁) private final ReentrantLock lock =new ReentrantLock(); @Override public void run() { while(true) { try{ lock.lock();//加锁 if(ticketNums>0){ try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(ticketNums--); }else{ break; } }finally{ //解锁 lock.unlock(); } } } }
方法名 | 作用 |
---|---|
wait() | 表示线程一直等待,知道其他线程通知,与sleep不同,会释放锁 |
wait(long timeout) | 指定等待的毫秒数 |
notify() | 唤醒一个处于等待状态的线程 |
notifyAll() | 唤醒同一个对象上所有调用wait()方法的线程,优先级别高的线程优先调度 |
//生产者 消费者 产品 缓冲区 public class TestPC { public static void main(String[] args) { SynContainer container=new SynContainer(); new Productor(container).start(); new Consumer(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++) { System.out.println("生产了"+i+"只鸡"); container.push(new Chicken(i)); } } } //消费者 class Consumer extends Thread{ SynContainer container; public Consumer(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;//需要产品编号. //构造方法 alt+insert public Chicken(int id) { this.id = id; } } //缓冲区 class SynContainer { //需要一个容器大小 Chicken[] chickens = new Chicken[10]; int count = 0;//容器计数器 //生产者放入产品 (synchronized 实现同步) 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; } }
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 { //演员表演,观众等待 True //观众观看,演员等待 False String voice;//表演的节目 boolean flag=true;//设置标志位,判断演员是否表演 //表演 public synchronized void play(String voice){ if(!flag){ //若观众观看的时候,演员需等待 this.wait(); 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){ //若演员表演的时候。观众需等待 this.wait(); try { this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println("观众观看了:"+voice); //观众观看完通知演员表演 this.notifyAll(); this.flag=!this.flag; } }
背景:经常创建和销毁、使用量特别大的资源,比如并发情况下的线程,对性能影响很大
思路:提前创建好多个线程,放入线程池中,使用时直接获取,使用完后放回池中
可以避免频繁创建销毁,实现重复利用。类似生活中的公共交通工具
好处
提高响应速度(减少了创建新线程的时间)
降低资源消耗(重复利用线程池中线程,不需要每次都创建)
便于线程管理(…)
重点
JDK5.0起提供了线程池相关API:ExecutorService和Executors
ExecutorService:真正的线程池接口。常见子类ThreadPoolExcutor
void execute(Runnable command):执行任务/命令,没有返回值,一般用来执行Runnable
Future submit(Callable ask):执行任务,有返回值,一般又来执行Callable
void shutdown():关闭连接池
Executors:工具类、线程池的工厂类,用于创建并返回不用类型的线程池
//测试线程池 public class TestPool { public static void main(String[] args) { //1.创建服务,创建线程池 //newFixedThreadPool 参数为线程池的大小 ExecutorService service= Executors.newFixedThreadPool(10); //执行 service.execute(new MyTread()); service.execute(new MyTread()); service.execute(new MyTread()); service.execute(new MyTread()); //2.关闭连接池 service.shutdown(); } } class MyTread implements Runnable{ @Override public void run() { System.out.println(Thread.currentThread().getName()); } }