线程创建
三种创建方式
Thread
//创建线程方式一:继承Thread类,重写run()方法,调用start开启线程 //总结:注意,线程开启不一定立即执行,由CPU调度执行 public class TestThread1 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线程,主线程 //创建一个线程对象 TestThread1 testThread1 = new TestThread1(); //调用start()方法开启线程 testThread1.start(); for (int i = 0; i < 20; i++) { System.out.println("我在学习---"+i); } } }
实现Runnable
package com.hua.demo; import org.apache.commons.io.FileUtils; import java.io.File; import java.io.IOException; import java.net.URL; //练习Thread,实现多线程下同步下载图片 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() { WebDownloader webDownloader = new WebDownloader(); webDownloader.downloader(url,name); System.out.println("下载了文件名为:"+name); } public static void main(String[] args) { TestThread2 t1 = new TestThread2("https://img0.bdstatic.com/static/searchresult/img/baseimg1_bb5ea3d.png","1.jpg"); TestThread2 t2 = new TestThread2("https://img0.bdstatic.com/static/searchresult/img/baseimg2_c615985.png","2.jpg"); TestThread2 t3 = new TestThread2("https://img0.bdstatic.com/static/searchresult/img/baseimg4_bc62837.png","3.jpg"); //先下载t1 t1.start(); //然后是t2 t2.start(); //最后是t3 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方法出现问题"); } } }
package com.hua.demo; import java.util.Date; //创建线程方式2:实现runnable接口,重写run方法,执行线程需要丢入runnable接口实现类,调用start方法 public class TestThread3 implements Runnable { @Override public void run() { //run方法线程体 for (int i = 0; i < 20; i++) { System.out.println("我在吃饭----"+i); } } public static void main(String[] args) { //创建runnbale接口的实现类对象 TestThread3 thread3 = new TestThread3(); //创建线程对象,通过线程对象来开启我们的线程,代理 new Thread(thread3).start(); for (int i = 0; i < 20; i++) { System.out.println("我在学习---"+i); } } }
并发问题
package com.hua.demo; //多个线程同时操作同一个对象 //买火车的例子 //发现问题:多个线程操作同一个资源的情况下,线程不安全,数据紊乱 public class TestThread4 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) { TestThread4 ticket = new TestThread4(); new Thread(ticket,"小明").start(); new Thread(ticket,"张三").start(); new Thread(ticket,"黄牛").start(); } }
案例:龟兔赛跑-Race
1、首先来个赛道距离。然后要离终点越来越近
2、判断比赛是否结束
package com.hua.demo; //模拟龟兔赛跑 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(1); } catch (InterruptedException e) { e.printStackTrace(); } } //判断比赛是否结束 boolean flag = gameOver(i); if (flag){ break; } System.out.println(Thread.currentThread().getName()+"--->跑了"+i+"步"); } } //判断是否完成比赛 public 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接口
1、实现Callable接口,需要返回值类型
2、重写call方法,需要抛出异常
3、创建目标对象
4、创建执行服务:ExecutorService ser = Executors.newFixedThreadPool(1);
5、提交执行:Future<Boolean> result = ser.submit(t1);
6、获取结果:boolean r1 = result.get()
7、关闭服务:ser.shutdownNow();
package com.hua.demo; 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() { WebDownloader1 downloader = new WebDownloader1(); downloader.downloader(url,name); System.out.println("下载了文件名为:"+name); return true; } public static void main(String[] args) throws ExecutionException, InterruptedException { TestCallable t = new TestCallable("https://cambrian-images.cdn.bcebos.com/ca301075b8ec31caeffd466f09c53a21_1528724735774.jpeg","1.png"); //创建执行服务: ExecutorService ser = Executors.newFixedThreadPool(1); //提交执行: Future<Boolean> result = ser.submit(t); //获取结果: boolean r = result.get(); System.out.println(r); //关闭服务: ser.shutdownNow(); } } class WebDownloader1 { public void downloader(String url,String name){ try { FileUtils.copyURLToFile(new URL(url),new File(name)); } catch (IOException e) { e.printStackTrace(); } }
静态代理
你:真实角色
婚庆公司:代理你,帮你处理结婚的事
结婚:实现结婚即可
package com.hua.demo; //静态代理模式总结 //真实对象和代理对象都要实现同一个接口 //代理对象要代理真实角色 //好处: //代理对象可以做很多真实对象做不了的事情 //真实对象专注做自己的事情 public class StaticProxy { public static void main(String[] args) { You you = new You();//你要结婚 //Thread类实现了Runnable接口 new Thread( () -> System.out.println("我爱你")).start(); new WeddingCompany(new You()).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 before() { System.out.println("结婚之前,布置现场"); } private void after() { System.out.println("结婚之后,收尾款"); } }
我的一生
第1章-废物的一生
第50章-糟糕的婴儿
第300章-莫欺少年穷
第600章-莫欺中年穷
第1000章-莫欺老年穷
第1100章-不详的离去
第1101章-棺材板的震动
第1150章-盗墓贼的眼泪
第1200章-死者为大