多线程
三种创建方式
-
thread class:继承Thread类
不建議使用:避免OOP单继承局限性
package thread; //创建线程方式一,继承Thread类,重写run()方法,调用start开启线程 /** * 总结: * 线程开启不一定立即执行,由CPU调度执行 */ public class Demo01 extends Thread{ @Override public void run() { //run方法线程体 for (int i = 0; i <20 ; i++) { System.out.println("我在看代码——————————"+i); } } public static void main(String[] args) { //创建一个线程对象 Demo01 demo01=new Demo01(); //调用start()方法,开启线程 demo01.start(); //主方法线程体 for (int i = 0; i < 20; i++) { System.out.println("我在学习多线程————————"+i); } } }
执行结果:
我在学习多线程————————0
我在学习多线程————————1
我在学习多线程————————2
我在学习多线程————————3
我在学习多线程————————4
我在看代码——————————0
我在看代码——————————1
我在看代码——————————2
我在看代码——————————3
我在看代码——————————4
我在学习多线程————————5
我在看代码——————————5
我在学习多线程————————6
我在看代码——————————6
我在学习多线程————————7
我在看代码——————————7
我在学习多线程————————8
我在看代码——————————8
我在学习多线程————————9
我在看代码——————————9
我在看代码——————————10
我在看代码——————————11
我在看代码——————————12
我在看代码——————————13
我在学习多线程————————10
我在学习多线程————————11
我在学习多线程————————12
我在学习多线程————————13
我在学习多线程————————14
我在学习多线程————————15
我在学习多线程————————16
我在学习多线程————————17
我在学习多线程————————18
我在学习多线程————————19
我在看代码——————————14
我在看代码——————————15
我在看代码——————————16
我在看代码——————————17
我在看代码——————————18
我在看代码——————————19
package thread; import org.apache.commons.io.FileUtils; import java.io.File; import java.io.IOException; import java.net.URL; //练习Thread,实现多线程同步下载图片 public class TestThread extends Thread{ private String url;//网络图片地址 private String name;//保存的图片名 public TestThread(String url,String name){ this.url=url; this.name=name; } @Override 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("https://i0.hdslb.com/bfs/manga-static/7dd3275b17fd83e041d518942eab2ca9ffc1be7e.jpg","哔哩哔哩图片1.jpg"); TestThread t2 =new TestThread("https://i0.hdslb.com/bfs/manga-static/b60f860c35f92b110766210f226e88362877d87d.jpg","哔哩哔哩图片2.jpg"); TestThread t3 =new TestThread("https://i0.hdslb.com/bfs/manga-static/96d800b2a5957ad8caf7e27d5c4909b3211a05e0.jpg","哔哩哔哩图片3.jpg"); TestThread t4 =new TestThread("https://i0.hdslb.com/bfs/manga-static/897b4ea69681a14141f9ef129258021fad007d74.jpg","哔哩哔哩图片4.jpg"); t1.start(); t2.start(); t3.start(); t4.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方法出现问题"); } } }
执行结果:
下载了文件名为:哔哩哔哩图片2.jpg
下载了文件名为:哔哩哔哩图片4.jpg
下载了文件名为:哔哩哔哩图片3.jpg
下载了文件名为:哔哩哔哩图片1.jpg
-
Runnable接口:实现Runnable接口
建议使用:避免单继承局限性,灵活方便,方便同一个对象被多个线程使用
package thread; //创建线程方式2:实现Runnable接口,重写run()方法,执行线程需要丢入Runnable接口实现类,调用Start方法 public class TeatThread2 implements Runnable{ @Override public void run() { //run方法线程体 for (int i = 0; i <20 ; i++) { System.out.println("我在看代码——————————"+i); } } public static void main(String[] args) { //创建一个Runnable接口实现类对象 TeatThread2 teatThread2=new TeatThread2(); //创建线程对象,通过线程对象来开启我们的线程:代理 //Thread thread=new Thread(teatThread2); //调用start()方法,开启线程 // thread.start(); new Thread(teatThread2).start(); //主方法线程体 for (int i = 0; i < 20; i++) { System.out.println("我在学习多线程————————"+i); } } }
运行结果:
我在学习多线程————————0
我在学习多线程————————1
我在学习多线程————————2
我在学习多线程————————3
我在看代码——————————0
我在看代码——————————1
我在看代码——————————2
我在学习多线程————————4
我在看代码——————————3
我在学习多线程————————5
我在学习多线程————————6
我在学习多线程————————7
我在学习多线程————————8
我在学习多线程————————9
我在学习多线程————————10
我在学习多线程————————11
我在学习多线程————————12
我在学习多线程————————13
我在学习多线程————————14
我在学习多线程————————15
我在看代码——————————4
我在学习多线程————————16
我在学习多线程————————17
我在看代码——————————5
我在看代码——————————6
我在看代码——————————7
我在看代码——————————8
我在看代码——————————9
我在看代码——————————10
我在看代码——————————11
我在看代码——————————12
我在看代码——————————13
我在学习多线程————————18
我在看代码——————————14
我在学习多线程————————19
我在看代码——————————15
我在看代码——————————16
我在看代码——————————17
我在看代码——————————18
我在看代码——————————19
package thread; import org.apache.commons.io.FileUtils; import java.io.File; import java.io.IOException; import java.net.URL; public class TestThread4 implements Runnable{ private String url;//网络图片地址 private String name;//保存的图片名 public TestThread4(String url,String name){ this.url=url; this.name=name; } @Override public void run() { WebDownloader2 webDownloader=new WebDownloader2(); webDownloader.downloader(url,name); System.out.println("下载了文件名为:"+name); } public static void main(String[] args) { TestThread t1 =new TestThread("https://i0.hdslb.com/bfs/manga-static/7dd3275b17fd83e041d518942eab2ca9ffc1be7e.jpg","哔哩哔哩图片5.jpg"); TestThread t2 =new TestThread("https://i0.hdslb.com/bfs/manga-static/b60f860c35f92b110766210f226e88362877d87d.jpg","哔哩哔哩图片6.jpg"); TestThread t3 =new TestThread("https://i0.hdslb.com/bfs/manga-static/96d800b2a5957ad8caf7e27d5c4909b3211a05e0.jpg","哔哩哔哩图片7.jpg"); TestThread t4 =new TestThread("https://i0.hdslb.com/bfs/manga-static/897b4ea69681a14141f9ef129258021fad007d74.jpg","哔哩哔哩图片8.jpg"); new Thread(t1).start(); new Thread(t2).start(); new Thread(t3).start(); new Thread(t4).start(); } } //下载器 class WebDownloader2{ //下载方法 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方法出现问题"); } } }
运行结果:
下载了文件名为:哔哩哔哩图片6.jpg
下载了文件名为:哔哩哔哩图片7.jpg
下载了文件名为:哔哩哔哩图片5.jpg
下载了文件名为:哔哩哔哩图片8.jpg
-
Callable接口:实现Callable接口
package thread; import org.apache.commons.io.FileUtils; import java.io.File; import java.io.IOException; import java.net.URL; import java.util.concurrent.*; //线程创建方式三:实现Callable接口 /** * 实现Callable接口的好处: * 1.可以定义返回值 * 2.可以抛出异常 */ 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() { WebDownloader3 webDownloader=new WebDownloader3(); webDownloader.downloader(url,name); System.out.println("下载了文件名为:"+name); return true; } public static void main(String[] args) { TestCallable t1 =new TestCallable("https://i0.hdslb.com/bfs/manga-static/7dd3275b17fd83e041d518942eab2ca9ffc1be7e.jpg","哔哩哔哩图片11.jpg"); TestCallable t2 =new TestCallable("https://i0.hdslb.com/bfs/manga-static/b60f860c35f92b110766210f226e88362877d87d.jpg","哔哩哔哩图片12.jpg"); TestCallable t3 =new TestCallable("https://i0.hdslb.com/bfs/manga-static/96d800b2a5957ad8caf7e27d5c4909b3211a05e0.jpg","哔哩哔哩图片13.jpg"); TestCallable t4 =new TestCallable("https://i0.hdslb.com/bfs/manga-static/897b4ea69681a14141f9ef129258021fad007d74.jpg","哔哩哔哩图片14.jpg"); //创建执行服务 ExecutorService service= Executors.newFixedThreadPool(4); //提交执行 Future<Boolean>result1=service.submit(t1); Future<Boolean>result2=service.submit(t2); Future<Boolean>result3=service.submit(t3); Future<Boolean>result4=service.submit(t4); //获取结果 try { boolean rs1=result1.get(); boolean rs2=result2.get(); boolean rs3=result3.get(); boolean rs4=result4.get(); } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); } //关闭服务 service.shutdownNow(); } } //下载器 class WebDownloader3{ //下载方法 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方法出现问题"); } } }
运行结果:
下载了文件名为:哔哩哔哩图片11.jpg
下载了文件名为:哔哩哔哩图片12.jpg
下载了文件名为:哔哩哔哩图片13.jpg
下载了文件名为:哔哩哔哩图片14.jpg
Lamda表达式
package thread; //推到Lambda表达式 public class TestLambda01 { //3静态内部类 //实现接口 static class Like2 implements ILike{ @Override public void lambda() { System.out.println("I Like Lambda2!"); } } public static void main(String[] args) { ILike iLike=new Like(); iLike.lambda(); iLike=new Like2(); iLike.lambda(); //4局部内部类 class Like3 implements ILike{ @Override public void lambda() { System.out.println("I Like Lambda3!"); } } iLike=new Like3(); iLike.lambda(); //5匿名内部类,没有类的名称,必须借助接口或者父类 iLike=new ILike() { @Override public void lambda() { System.out.println("I Like Lambda4!"); } }; iLike.lambda(); //6用Lambda简化 iLike=() ->{ System.out.println("I Like Lambda5!"); }; iLike.lambda(); } } //1定义一个函数接口 interface ILike{ void lambda(); } //2实现接口 class Like implements ILike{ @Override public void lambda() { System.out.println("I Like Lambda!"); } }
运行结果:
I Like Lambda!
I Like Lambda2!
I Like Lambda3!
I Like Lambda4!
I Like Lambda5!
线程休眠——sleep
package thread; import com.sun.scenario.effect.impl.sw.sse.SSEBlend_SRC_OUTPeer; import java.text.SimpleDateFormat; import java.util.Date; //模拟倒计时 public class TestSleep2 implements Runnable{ public static void main(String[] args) { try { tenDown(); } catch (InterruptedException e) { e.printStackTrace(); } //打印当前系统时间 Date date=new Date(System.currentTimeMillis());//获取系统当前时间 int i=0; while (true){ try { Thread.sleep(1000); System.out.println(new SimpleDateFormat("HH:mm:ss").format(date)); date=new Date(System.currentTimeMillis());//更新系统当前时间 } catch (InterruptedException e) { e.printStackTrace(); } i++; if(i>10){ break; } } } //模拟倒计时 public static void tenDown() throws InterruptedException { int number=10; while (true){ Thread.sleep(1000); System.out.println(number--); if(number<=0){ break; } } } @Override public void run() { } }
运行结果:
10 9 8 7 6 5 4 3 2 1 14:10:35 14:10:36 14:10:37 14:10:38 14:10:39 14:10:40 14:10:41 14:10:42 14:10:43 14:10:44 14:10:45
线程礼让_yield
package thread; //线程礼让:礼让不一定成功,看CPU心情 public class TestYield { public static void main(String[] args) { MyYield myYield=new MyYield(); new Thread(myYield,"晓红").start(); new Thread(myYield,"小军").start(); } } class MyYield implements Runnable{ @Override public void run() { System.out.println(Thread.currentThread().getName()+"线程开始执行"); Thread.yield();//礼让 System.out.println(Thread.currentThread().getName()+"线程停止执行"); } }
运行结果:
小军线程开始执行
晓红线程开始执行
小军线程停止执行
晓红线程停止执行
线程强制执行_join
合并线程,待此线程执行完后,在执行其他线程,会造成线程堵塞,不建议使用
线程同步机制
并发:同一个对象被多个线程同时操作
使用synchronized同步方法(锁的是this)解决
管理法
package threadSyn; import com.sun.org.apache.bcel.internal.generic.NEW; //测试生产者消费者模型--->利用缓冲区解决:管程法 //生产者,消费者,产品,缓冲区 public class TestPC { public static void main(String[] args) { SynContainer synContainer=new SynContainer(); new Productor(synContainer).start(); new Consumer(synContainer).start(); } } //生产者 class Productor extends Thread{ SynContainer synContainer; public Productor(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 Consumer extends Thread{ SynContainer synContainer; public Consumer(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;//产品编号 public Chicken(int id) { this.id = id; } } //缓冲区 class SynContainer{ //需要一个容器大小 Chicken[] chickens=new Chicken[10]; //容器计数器 int num=0; //生产者放入产品 public synchronized void push(Chicken chicken){ //如果容器满了,就要等待消费者消费 if(num==chickens.length){ //通知消费者消费,生产者等待 try { this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } //如果没有满,我们就需要丢入产品 chickens[num]=chicken; num++; //可以通知消费者消费了 this.notifyAll(); } //消费者消费产品 public synchronized Chicken pop(){ //判断能否消费 if(num==0){ //等待生产者生产,消费者等待 try { this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } //如果可以消费 num--; Chicken chicken=chickens[num]; //吃完了,通知消费者生产 this.notifyAll(); return chicken; } }
信号灯法
package threadSyn; //测试生产者消费者:信号灯法,标志为解决 public class TestPC2 { public static void main(String[] args) { TV tv=new TV(); new Plays(tv).start(); new Watchs(tv).start(); } } //生产者-->演员 class Plays extends Thread{ TV tv; public Plays(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 Watchs extends Thread{ TV tv; public Watchs(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 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.flag=!this.flag; this.notifyAll(); } }