java线程相关概念及线程的各种状态
一、Lambda表达式
1.λ
- λ希腊字母表中排序第十一位的字母,英语名称为Lambda
- 避免匿名内部类定义过多
- 其实质属于函数式编程的概念
2.为什么要使用lambda表达式:
- 避免匿名内部类定义过多
- 可以让代码看起来很简洁
- 去掉了一堆没有意义的代码,只留下核心的逻辑
3.函数式接口
-
理解Functional Interface(函数式接口)是学习java8 lambda表达式的关键所在
-
函数式接口的定义
- 任何接口,如果只包含唯一一个抽象方法,那么它就是一个函数式接口
- 对于函数式接口,我们可以通过lambda表达式来创建接口的对象
-
lambda表达式的推导
-
//lambda表达式的推导 //外部类->静态内部类->局部内部类->匿名内部类->lambda表达式简化 public class LambdaTest { //2.静态内部类 static class Like2 implements Ilikeable{ @Override public void like() { System.out.println("lambda静态内部类"); } } public static void main(String[] args) { Ilikeable like = new Like(); like.like(); like=new Like2(); like.like(); //3.局部内部类 class Like3 implements Ilikeable{ @Override public void like() { System.out.println("lambda局部内部类"); } } like=new Like3(); like.like(); //4.匿名内部类,没有类的名称,只能借助接口或者父类 like=new Ilikeable() { @Override public void like() { System.out.println("lambda匿名内部类"); } }; like.like(); //5.lambda表达式(JDK1.8),函数式接口,只有一个要需要重写的方法,所以不需要知道名称 like=() ->{ System.out.println("lambda表达式"); }; like.like(); } } //1.外部类 class Like implements Ilikeable{ @Override public void like() { System.out.println("lambda测试外部类"); } } //外部接口 interface Ilikeable{ void like(); }
-
-
lambda表达式的进一步简化
-
多个参数,参数类型可省略(要不写全不写),括号必须保留
-
多条语句,方法体括号必须保留
-
public class LambdaTest2 { public static void main(String[] args) { Ilovable love=(int i)-> { System.out.println("I love you-->"+i); }; love.love(520); //1.简化参数类型 love=(i)-> { System.out.println("I love you-->"+i); }; love.love(521); //2.简化括号,如果有多个参数,则不能简化括号 love=i-> { System.out.println("I love you-->"+i); }; love.love(522); //3.简化花括号,如果有多条语句,则必须用花括号 love=i->System.out.println("I love you-->"+i); love.love(523); } } interface Ilovable{ void love(int i); }
-
二、静态代理
-
代理对象和真实对象都要实现同一个接口
-
代理对象代理真实对象来进行事情的处理
-
好处
-
代理对象可以做很多真实对象做不了的事
-
真实对象可以专注做自己的事情
-
//静态代理,与Thread的实现相似
public class StaticProxy {
public static void main(String[] args) {
You you = new You();
WeddingCompany weddingCompany = new WeddingCompany(you);
weddingCompany.marry();
new Thread(new Runnable() {
@Override
public void run() {
}
}).start();
new WeddingCompany(new IMarryable() {
@Override
public void marry() {
System.out.println("test1");
}
}).marry();
new WeddingCompany(()->System.out.println("test2")).marry();//lambda表达式
}
}
//结婚接口
interface IMarryable{
void marry();
}
//真实要结婚的对象
class You implements IMarryable{
@Override
public void marry() {
System.out.println("我结婚了");
}
}
//婚庆公司
class WeddingCompany implements IMarryable{
private IMarryable target;
public WeddingCompany(IMarryable target) {
this.target = target;
}
@Override
public void marry() {
before();
this.target.marry();//调用真实对象的marry方法
after();
}
private void before() {
System.out.println("结婚前要婚庆公司布置现场");
}
private void after() {
System.out.println("结婚后婚庆公司要收尾款");
}
}
三、线程的五大状态及方法
-
线程方法
-
停止线程
-
不推荐使用JDK提供的stop()、destroy()方法【已废弃】。
-
推荐线程自己停止下来。
-
建议使用一个标志位进行终止线程,当flag=false时,则终止线程运行。
-
//线程停止 public class ThreadStopTest implements Runnable{ private static boolean flag=true; public static void main(String[] args) { ThreadStopTest th=new ThreadStopTest(); new Thread(th).start(); for (int i = 0; i < 1000; i++) { System.out.println("mainThread"+i); if (i==400){ th.stop(); } } } @Override public void run() { int i=0; while(flag){ System.out.println("subThread"+i++); } } public void stop(){ this.flag=false; } }
-
-
线程休眠
-
sleep(时间)指定当前线程阻塞的毫秒数
-
sleep存在异常InterruptedException
-
sleep时间达到后线程进入就绪状态
-
sleep可以模拟网络延时,倒计时等
-
第个对象都有一个锁,sleep不会释放锁
-
模拟网络延时:
-
//线程休眠,模拟网络延时,可以放大问题的发生性 public class ThreadSleep implements Runnable{ private int ticketnum=10; @Override public void run() { while(true){ if (ticketnum<=0){ break; } try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+"买了第"+ticketnum--+"张票");//会出现数据的混乱,线程不安全,不同步 } } public static void main(String[] args) { ThreadSleep testThread4 = new ThreadSleep(); new Thread(testThread4,"刘备").start(); new Thread(testThread4,"张飞").start(); new Thread(testThread4,"关羽").start(); } }
-
模拟倒计时:
public class ThreadSleep2 { public static void main(String[] args) throws InterruptedException { turnDown(); } //模拟10s的倒计时 public static void turnDown() throws InterruptedException { int num=10; while(true){ Thread.sleep(1000); System.out.println(num); num--; if (num==0){ break; } } } }
-
1s打印1次时间
import java.text.SimpleDateFormat; import java.util.Date; public class ThreadSleep2 { public static void main(String[] args) throws InterruptedException { //打印时间 Date date=new Date(System.currentTimeMillis());//获取当前系统时间 while(true){ //线程休眠1s Thread.sleep(1000); SimpleDateFormat simpleDateFormat=new SimpleDateFormat("yyyy-MM-dd HH mm ss"); System.out.println(simpleDateFormat.format(date)); date=new Date(System.currentTimeMillis());//更新当前时间 } } }
-
-
-
线程礼让(yield)
-
礼让线程,让当前正在执行的线程暂停,但不阻塞,就是说让线程从运行状态进入到就绪状态。
-
礼让不一定成功,由CPU调度。
-
public class ThreadYield implements Runnable{ @Override public void run() { System.out.println(Thread.currentThread().getName()+"Thread start"); Thread.yield();//下次执行依然由CPU调度 System.out.println(Thread.currentThread().getName()+"Thread end"); } public static void main(String[] args) { ThreadYield threadYield = new ThreadYield(); new Thread(threadYield).start(); new Thread(threadYield).start(); } }
-
-
线程合并(插队join)
-
Join合并线程,待此线程执行完成后,再执行其他线程,其他线程阻塞
-
可以想象成插队
-
强制执行,会让线程阻塞,少用
-
package status; //线程合并,强制执行,可以理解为插队,少用 public class ThreadJoin implements Runnable{ @Override public void run() { for (int i = 0; i < 1000; i++) { System.out.println("我是vip线程"+i); } } public static void main(String[] args) { ThreadJoin threadJoin = new ThreadJoin(); Thread thread = new Thread(threadJoin); thread.start(); //主线程执行 for (int i = 0; i < 200; i++) { if (i==100){ try { thread.join(); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println("我是主线程"+i); } } }
-
-
观测线程状态
package status; //观测线程状态 public class ThreadStatus { public static void main(String[] args) throws InterruptedException { Thread thread = new Thread(()->{ for (int i = 0; i < 5; i++) { try { Thread.sleep(1000);//子线程休眠1s } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println("子线程执行完毕"); }); //new状态,未调用start Thread.State state = thread.getState(); System.out.println(state); //线程开始执行 thread.start(); state=thread.getState(); System.out.println(state); //不结束则一直输出状态 while(state!=Thread.State.TERMINATED){ //主线程1S执行一次 Thread.sleep(1000); state=thread.getState(); System.out.println(state); } } }
-
线程优先级:设置优先级后也是需要看CPU调度,并不一定按优先级执行,只是说优先级高的线程分配的“权重”大。
-
package status; //优先级0-10 public class ThreadPriorityDemo01 { public static void main(String[] args) { //输出主线程的优先级,默认优先级为5 System.out.println(Thread.currentThread().getName()+"-->"+Thread.currentThread().getPriority()); SetPriorityTest setPriorityTest=new SetPriorityTest(); Thread t1=new Thread(setPriorityTest); Thread t2=new Thread(setPriorityTest); Thread t3=new Thread(setPriorityTest); Thread t4=new Thread(setPriorityTest); Thread t5=new Thread(setPriorityTest); t1.setPriority(10); t1.start(); t2.setPriority(8); t2.start(); t3.setPriority(6); t3.start(); t4.setPriority(4); t4.start(); t5.setPriority(1); t5.start(); } } class SetPriorityTest implements Runnable{ @Override public void run() { System.out.println(Thread.currentThread().getName()+"-->"+Thread.currentThread().getPriority()); } }
-
-
守护线程:
-
所谓守护线程,是指在程序运行的时候在后台提供一种通用服务的线程,比如垃圾回收线程就是一个很称职的守护者,并且这种线程并不属于程序中不可或缺的部分。因此,当所有的非守护线程结束时,程序也就终止了,同时会杀死进程中的所有守护线程。反过来说,只要任何非守护线程还在运行,程序就不会终止。
-
用户线程和守护线程两者几乎没有区别,唯一的不同之处就在于虚拟机的离开:如果用户线程已经全部退出运行了,只剩下守护线程存在了,虚拟机也就退出了。 因为没有了被守护者,守护线程也就没有工作可做了,也就没有继续运行程序的必要了。
-
线程分为用户线程和守护线程,正常的线程都是用户线程
-
虚拟机必须确保用户线程执行完毕
-
虚拟机不用等待守护线程执行完毕
-
package status; public class GodAndYouDemo { public static void main(String[] args) { God god=new God(); You you=new You(); Thread godThread=new Thread(god); Thread youThread=new Thread(you); godThread.setDaemon(true);//默认为false godThread.start(); youThread.start(); } } //God,守护者(守护线程) class God implements Runnable{ @Override public void run() { while(true) System.out.println("我是god,我一直在守护着you"); } } //You,被守护者(用户线程) class You implements Runnable{ @Override public void run() { for (int i = 0; i <100; i++) { System.out.println("我是you,这是我的第"+i+"天"); } System.out.println("===Good bye==="); } }
-
用户线程执行完成后,守护线程在运行一会自动退出
-
本文来自博客园,作者:一只快乐的小67,转载请注明原文链接:https://www.cnblogs.com/sp520/p/16212261.html