多线程学习1(线程的三种创建方式,lambda表达式,线程的状态)
一.线程的三种创建方式
1.继承Thread类
package demo01;//创建线程方式一,继承thread类 ,重写run()方法,调用start开启线程 //总结:线程开始,不一定立即执行,由cpu调度执行 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 testThread1 = new TestThread(); testThread1.start(); for (int i = 0; i < 500; i++) { System.out.println("我在学习多线程"+i); } } }
2.实现Runable接口
优点:避免单继承的局限性,灵活方便,方便同一个对象被多个线程所使用
package demo01; //创建线程方式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){ //创建runnable接口的实现类对象 TestThread3 testThread3 = new TestThread3(); //创建线程对象,通过线程对象来开启线程,代理 //Thread hread = new Thread(testThread3); //thread.start(); new Thread(testThread3).start(); for (int i = 0; i < 500; i++) { System.out.println("我在学习多线程"+i); } } }
3.实现callable接口
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 ExecutionException, InterruptedException { TestCallable t1 = new TestCallable("https://profile.csdnimg.cn/0/8/D/1_weixin_43822647","1.jpg"); TestCallable t2 = new TestCallable("https://profile.csdnimg.cn/0/8/D/1_weixin_43822647","2.jpg"); TestCallable t3 = new TestCallable("https://profile.csdnimg.cn/0/8/D/1_weixin_43822647","3.jpg"); //创建执行服务 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异常"); } }
二.lambda表达式
package lambda; /* 推导lambda表达式 */ public class TestLamda1{ //3.静态内部类 static class Like2 implements Ilike{ @Override public void lambda() { System.out.println("i like lambda2"); } } public static void main(String[] args) { Ilike like = new Like(); like.lambda(); Ilike like2 = new Like2(); like2.lambda(); //4.局部内部类 class Like3 implements Ilike{ @Override public void lambda() { System.out.println("i like lambda3"); } } Ilike like3 = new Like3(); like3.lambda(); //5.匿名内部类 like = new Ilike() { @Override public void lambda() { System.out.println("i like lambda4"); } }; like.lambda(); //6.用lambda简化 like = ()->{ System.out.println("i like lambda5"); }; like.lambda(); } } //1.定义一个函数接口(只有一个抽象方法的接口) interface Ilike{ void lambda(); } //2.实现类 class Like implements Ilike{ @Override public void lambda() { System.out.println("i like lambda"); } }
三.线程状态
1.线程的停止
不推荐使用jdk提供的stop(),destroy()方法,推荐让线程自己停下来,建议使用一个标志位,当flag=false线程终止
package state; //测试停止线程 //1.建议线程正常停止--->利用次数,不建议死循环 //2.建议使用标志位--->设置一个标志位 //3.不要使用stop或destroy等过时或者JDK不建议使用的方法 public class TestStop implements Runnable{ //标志位 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) { 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("线程停止了"); } } } }
2.线程的休眠
sleep不会释放锁
可以放大问题的发生性,模拟网络延时
可以模拟倒计时
package state; import demo01.TestThread4; //模拟网络延时:放大问题的发生性 public class TestSleep implements Runnable { //票数 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 testThread4 = new TestThread4(); new Thread(testThread4, "小明").start(); new Thread(testThread4, "老师").start(); new Thread(testThread4, "黄牛").start(); } }
3.线程礼让Yield
将线程从运行太转为就绪态
package state; //测试礼让线程 //礼让不一定成功,看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()+"线程停止执行"); } }
4.线程强制执行
可以想象为插队,强制一个线程执行直至其结束
package state; //测试Join方法,想象为插队 public class TestJoin implements Runnable{ @Override public void run() { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } for (int i = 0; i < 1000; i++) { System.out.println("线程vip来了"+i); } } public static void main(String[] args) throws InterruptedException { //启动线程 TestJoin testJoin = new TestJoin(); Thread thread=new Thread(testJoin); thread.start(); for (int i = 0; i < 500; i++) { if(i==200){ thread.join(); } System.out.println("main"+i); } } }
5.观测线程状态state
NEW, RUNNABLE, BLOCKED, WAITING, TIMED_WAITING, TERMINATED
package state; //观察线程状态 public class TestState { 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(100); state = thread.getState();//更 新进程状态 System.out.println(state); } } }
6线程优先级
高优先级的线程更容易执行,但还是要看cpu的心情
package state; //测试线程的优先级 public class TestPriority { 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); Thread t5= new Thread(myPriority); Thread t6= new Thread(myPriority); //设置优先级,再启动 t1.start(); t2.setPriority(1); t2.start(); t3.setPriority(4); t3.start(); t4.setPriority(Thread.MAX_PRIORITY); t4.start(); t5.setPriority(8); t5.start(); t6.setPriority(7); t6.start(); } } class MyPriority implements Runnable{ @Override public void run(){ System.out.println(Thread.currentThread().getName() + "-->" +Thread.currentThread().getPriority()); } }
7.守护线程
虚拟机必须确保用户线程执行完毕,不用等待守护线程执行完毕,守护线程常用来监控内存,垃圾回收,后台记录操作日志
package 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("==============goodebye!world!============"); } }