多线程02
静态代理
演示实现静态代理对比Thread
package com.company.demo03;
//静态代理模式总结:
//真实对象和代理对象都要实现同一个接口
//代理对象要代理真实角色
//好处;
// 代理对象
// 真实对象专注做自己的事情
public class StaticProxy {
public static void main(String[] args) {
You you=new You ();//你要结婚
new Thread (()-> System.out.println ("我爱你")).start ();
new WeddingCommpany (new You ()).HappyMarry ();
}
}
interface Marry{
// 人间四大喜事
// 久旱逢甘露
// 他乡遇故知
// 金榜题名时
void HappyMarry();
}
//真实角色,你去结婚
class You implements Marry{
@Override
public void HappyMarry() {
System.out.println ("qin老师要结婚了");
}
}
//代理角色,帮助你结婚
class WeddingCommpany implements Marry{
private Marry target;
public WeddingCommpany(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 ("结婚之后,收尾款");
}
}
Lambda表达式
-
λ希腊字母表中排序第十一位的字母,英文名lambda
-
避免匿名内部类定义过多
-
其实质属于函数式编程的概念
(params)->expression[表达式] (params)->statement[语句] (params)->{statements}
a->System.out.println("i like lambda-->"+a);
new Thread(()->System.out("多线程学习。。。。。。。")).start();
-
为什么要用lambda表达式
- 避免匿名内部类定义太多
- 可以让你的代码看起来很简洁
- 去掉一堆没有意义的代码,只留下核心的逻辑
-
理解Functional interface(函数式接口)是学习Java8 lambda表达式的关键所在
-
函数式接口的定义:
-
任何接口,如果只包含唯一一个抽象方法,那么他就是一个函数式接口。
public interface Runnable{ public abstract void run(); }
-
对于函数式接口,我们可以通过lambda表达式来创建该接口的对象
-
package com.lambda;
/*
推导lambda表达式
*/
public class TestLambda {
//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 ();
like = new like2 ();
like.lambda ();
//4.局部内部类
class like3 implements ILike{
@Override
public void lambda() {
System.out.println ("i like lambda3");
}
}
like = new like3 ();
like.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");
}
}
package com.lambda;
public class TestLambda2 {
public static void main(String[] args) {
ILove love=null;
//简化2.简化括号
love = (a,b,c)->{
System.out.println ("i love you-->"+a+b+c);
System.out.println ("i love you-->too");
};
//总结:
//lambda表达式只能有一行代码的情况下才能简化成为一行,如果有多行,那么就用代码块包裹。
//前提是接口为函数式接口
//多个参数也可以去掉参数类型,要去掉就都去掉,必须加上括号,
love.love (521,300,200);
}
}
interface ILove{
void love(int a,int b,int c);
}
线程状态
五大状态
线程状态
线程休眠
package com.state;
public class TestSleep1 implements Runnable{
//票数
private int ticketNums = 10;
@Override
public void run() {
while (true){
if (ticketNums<=0){
break;
}
try {
Thread.sleep (1000);
} catch (InterruptedException e) {
e.printStackTrace ();
}
System.out.println (Thread.currentThread ().getName ()+"拿到了第"+ticketNums--+"票");
}
}
public static void main(String[] args) {
TestSleep1 ticket =new TestSleep1 ();
new Thread (ticket,"小明").start ();
new Thread (ticket,"老师").start ();
new Thread (ticket,"黄牛").start ();
}
}
模拟倒计时
package com.state;
//模拟倒计时
public class TestSleep2 {
public static void main(String[] args) {
try {
tenDown ();
} catch (InterruptedException e) {
e.printStackTrace ();
}
}
public static void tenDown() throws InterruptedException {
int num =10;
while (true){
Thread.sleep (1000);
System.out.println (num--);
if (num<=0){
break;
}
}
}
}
package com.state;
import java.text.SimpleDateFormat;
import java.util.Date;
//模拟倒计时
public class TestSleep2 {
public static void main(String[] args) {
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 ();
}
}
}
}
线程礼让
- 礼让线程,让当前正在执行的线程暂停,但不阻塞
- 将线程从运行状态转为就绪状态
- 让CPU重新调度,礼让不一定成功!看CPU心情
package com.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 ()+"线程停止执行");
}
}
jion
- jion合并线程,待此线程执行完成后,再执行其他线程,其他线程阻塞
- 可以想象成插队
package com.state;
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) throws InterruptedException {
// 启动我们的线程
TestJoin testJoin= new TestJoin ();
Thread thread = new Thread (testJoin);
thread.start ();
//主线程
for (int i = 0; i < 1000; i++) {
if (i==200){
thread.join();//cha
}
System.out.println ("main"+i);
}
}
}
线程状态观测
-
Thread.State
线程状态。线程可以处于以下状态之一:
-
NEW
尚未启动的线程出于此状态。
-
RUNNABLE
在java虚拟机中执行的线程出于此状态。
-
BLOCKED
被阻塞等待监视器锁定的线程出于此状态。
-
WAITING
正在等待另一个线程执行特定动作的线程出于此状态。
-
TIMED_WAITING
正在等待另一个线程执行动作达到指定等待时间的线程处于此状态。
-
TERMINATED
已退出的线程出于此状态。
一个线程可以在给定时间点出于一个状态。这些状态是不反映任何操作系统线程状态的虚拟机状态。
-
package com.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);//NEW
// 观察启动后
thread.start ();
state = thread.getState ();
System.out.println (state);//Run
while (state !=Thread.State.TERMINATED){//只要线程不终止,就一直输出状态
Thread.sleep (100);
state = thread.getState ();//更新线程状态
System.out.println (state);//输出状态
}
}
}
线程优先级
- Java提供一个线程调度器来监控程序中启动后进入就绪状态的所有线程,线程调度器按照优先级决定应该调度哪个线程来执行。
- 线程的优先级用数字表示,范围从1~10.
- Thread.MIN_PRIORITY = 1;
- Thread.MAX_PRIORITY = 10;
- Thread.NORM_PRIORITY = 5;
- 使用以下方式改变或获取优先级
- getPriority() . setPriority(int xxx)
优先级低只是意味着获得调度的概率低.并不是优先级低就不会被调用了.这都是看CPU的调度
守护线程
- 线程分为用户线程和守护线程
- 虚拟机必须确保用户线程执行完毕
- 虚拟机不用等待守护线程执行完毕
- 如,后台记录操作日志,监控内存,垃圾回收
package com.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);//默认是false表示用户线程,正常的线程都是用户线程。。。
thread.start ();//上帝守护线程启动
new Thread (you).start ();//你 用户线程启动
}
}
//上帝
class God implements Runnable{
@Override
public void run() {
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!=====-");//hello world!
}
}