Java多线程(review)

文章目录

  • 线程状态
  • 线程方法
  • 线程停止
  • 线程休眠——sleep
    • 网络延时
    • 模拟倒计时与打印当前系统时间
  • 线程礼让——yield
  • 线程强制执行——Join
  • 线程状态
  • 线程优先级
  • 守护线程
  • 不安全案例
  • 死锁
  • Lock锁

线程状态

在这里插入图片描述

  • 新建状态:
    使用 new 关键字和 Thread 类或其子类建立一个线程对象后,该线程对象就处于新建状态。它保持这个状态直到程序 start() 这个线程。
  • 就绪状态:
    当线程对象调用了start()方法之后,该线程就进入就绪状态。就绪状态的线程处于就绪队列中,要等待JVM里线程调度器的调度。
  • 运行状态:
    如果就绪状态的线程获取 CPU 资源,就可以执行 run(),此时线程便处于运行状态。处于运行状态的线程最为复杂,它可以变为阻塞状态、就绪状态和死亡状态。
  • 阻塞状态:
    如果一个线程执行了sleep(睡眠)、suspend(挂起)等方法,失去所占用资源之后,该线程就从运行状态进入阻塞状态。在睡眠时间已到或获得设备资源后可以重新进入就绪状态。可以分为三种:
  • 等待阻塞:运行状态中的线程执行 wait() 方法,使线程进入到等待阻塞状态。
  • 同步阻塞:线程在获取 synchronized 同步锁失败(因为同步锁被其他线程占用)。
  • 其他阻塞:通过调用线程的 sleep() 或 join() 发出了 I/O 请求时,线程就会进入到阻塞状态。当sleep() 状态超时,join() 等待线程终止或超时,或者 I/O 处理完毕,线程重新转入就绪状态。
  • 死亡状态:
    一个运行状态的线程完成任务或者其他终止条件发生时,该线程就切换到终止状态。

线程方法

方法说明
public void start()使该线程开始执行;Java 虚拟机调用该线程的 run 方法。
public void run()如果该线程是使用独立的 Runnable 运行对象构造的,则调用该 Runnable 对象的 run 方法;否则,该方法不执行任何操作并返回。
public final void setName(String name)改变线程名称,使之与参数 name 相同。
public final void setPriority(int priority)更改线程的优先级。
public final void setDaemon(boolean on)将该线程标记为守护线程或用户线程。
public final void join(long millisec)等待该线程终止的时间最长为 millis 毫秒。
public void interrupt()中断线程。
public final boolean isAlive()测试线程是否处于活动状态。

上述方法是被 Thread 对象调用的,下面表格的方法是 Thread 类的静态方法。

方法描述
public static void yield()暂停当前正在执行的线程对象,并执行其他线程。
public static void sleep(long millisec)在指定的毫秒数内让当前正在执行的线程休眠(暂停执行),此操作受到系统计时器和调度程序精度和准确性的影响。
public static boolean holdsLock(Object x)当且仅当当前线程在指定的对象上保持监视器锁时,才返回 true。
public static Thread currentThread()返回对当前正在执行的线程对象的引用。
public static void dumpStack()将当前线程的堆栈跟踪打印至标准错误流。

线程停止

  1. 建议线程正常停止–>利用次数,不建议死循环
  2. 建议使用标志位–>设置一个标志位
    设置一个公开的方法停止线程,转换标志位
  3. 不要使用stop或者destory等过时或者JDK不建议使用的方法
package com.zeng.state;
//测试停止线程
//1.建议线程正常停止-->利用次数,不建议死循环
//2。 建议使用标志位-->设置一个标志位
//3. 不要使用stop或者destory等过时或者JDK不建议使用的方法
public class TestStop implements Runnable{//设置一个标志位private boolean flag=true;@Overridepublic void run() {int i=0;while(flag){//当线程flag=false,则终止线程运行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){testStop.stop();System.out.println("线程停止");}}}
}

线程休眠——sleep

  • sleep(时间)指定当前线程阻塞的毫秒数;
  • sleep存在异常InterruptedException;
  • sleep时间达到后线程进入就绪状态
  • sleep可以模拟网络延时,倒计时等。
  • 每个对象都有一个锁,sleep不会释放锁。

网络延时

  • 模拟网络延时:扩大线程的发生性
package com.zeng.state;import com.zeng.demo01.TestThread03;
//模拟网络延时:扩大线程的发生性
public class TestSleep implements Runnable{//票数private int ticketNums=10;@Overridepublic 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) {TestThread03 ticket = new TestThread03();new Thread(ticket,"小明").start();new Thread(ticket,"老师").start();new Thread(ticket,"黄牛党").start();}
}

模拟倒计时与打印当前系统时间

package com.zeng.state;import java.text.SimpleDateFormat;
import java.util.Date;//模拟倒计时
public class TestSleep02 {public static void main(String[] args) throws InterruptedException {//模拟倒计时(调用静态方法)// tenDown();//打印当前系统时间Date startTime = new Date(System.currentTimeMillis());while(true){try {// Date startTime = new Date(System.currentTimeMillis());Thread.sleep(1000);System.out.println(new SimpleDateFormat("HH:mm:ss").format(startTime));startTime = new Date(System.currentTimeMillis());//获取当前时间} catch (InterruptedException e) {e.printStackTrace();}}}public static /*加上static可以直接调用(静态方法)*/void tenDown() throws InterruptedException {int num=10;while(true){Thread.sleep(1000);//sleep存在异常,抛出System.out.println(num--);if(num<=0){break;}}}
}

线程礼让——yield

  • 礼让线程,让正在执行的线程暂停,但不阻塞
  • 将线程状态转为就绪状态
  • 让CPU重新调度,礼让不一定成功!
package com.zeng.state;
//测试礼让线程
//礼让不一定成功,全看CPU心情
public class TextYield {public static void main(String[] args) {MyYield myYield = new MyYield();new Thread(myYield,"a").start();new Thread(myYield,"b").start();}
}
class MyYield implements Runnable{@Overridepublic void run() {System.out.println(Thread.currentThread().getName()+"线程开始执行");Thread.yield();//线程礼让System.out.println(Thread.currentThread().getName()+"线程停止执行");}
}

线程强制执行——Join

  • Join合并线程,待此线程执行完成后,再执行其他线程,其他线程阻塞
  • 可以想象成插队
package com.zeng.state;
//测试join方法 想象为插队
public class TestJoin implements Runnable{@Overridepublic 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();//插队}System.out.println("main"+i);}}
}

线程状态

线程状态。 线程可以处于以下状态之一:

状态说明
NEW尚未启动的线程处于此状态。
RUNNABLE在Java虚拟机中执行的线程处于此状态。
BLOCKED被阻塞等待监视器锁定的线程处于此状态。
WAITING正在等待另一个线程执行特定动作的线程处于此状态。
TIMED_WAITING正在等待另一个线程执行动作达到指定等待时间的线程处于此状态。
TERMINATED已退出的线程处于此状态。

一个线程可以在给定时间点处于一个状态。 这些状态是不反映任何操作系统线程状态的虚拟机状态。

package com.zeng.state;public class TestState {public static void main(String[] args) {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);//Runwhile(state!=Thread.State.TERMINATED){try {Thread.sleep(1000);state=thread.getState();System.out.println(state);} catch (InterruptedException e) {e.printStackTrace();}}//  thread.start();线程进入死亡状态后,就不能再启动,直接报错}
}

线程优先级

  • java提供一个线程调度器来监控程序中启动后进入就绪状态的所有线程,线程调度器按照优先级决定应该调度哪个线程来执行。
  • 线程的优先级用数字表示,范围从1~10;
    • Thread.MIN_PRIORITY=1;
    • Thread.MAX_PRIORITY=10;
    • Thread.NORM_PRIORITY=5;
  • 使用以下方式改变或获取优先级
    • getPriority().setPriority(int XXX)
    • 优先级的设定建议在start()调度前(先设置优先级,再启动
  • 优先级低只意味着获得调度的概率低,并不是优先级低就不会被调用了,这都是看CPU调度
package com.zeng.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);//MAX_PRIORITY=10t4.start();t5.setPriority(5);t5.start();t6.setPriority(7);t6.start();}
}
class MyPriority implements Runnable{@Overridepublic void run() {System.out.println(Thread.currentThread().getName()+"-->"+Thread.currentThread().getPriority());}
}

守护线程

  • 线程分为用户线程守护线程
  • 虚拟机必须保护用户线程执行完毕
  • 虚拟机不必等待守护线程执行完毕
  • 如,后台记录日志操作,监控内存,垃圾回收等待
package com.zeng.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{@Overridepublic void run() {while(true){System.out.println("上帝保佑着你");}}
}class You implements Runnable{@Overridepublic void run() {for (int i = 0; i < 30000; i++) {System.out.println("你一生都在开心的活着");}System.out.println("-=====goodbye world");}
}

不安全案例

package com.zeng.syn;
//不安全的买票
//线程不安全,有负数public class TestUnsafeBuyTicket {public static void main(String[] args) {BuyTicket station = new BuyTicket();new Thread(station,"我emo了").start();new Thread(station,"你笑了").start();new Thread(station,"可恶的黄牛").start();}
}class BuyTicket implements Runnable{//票private int  ticketNums=10;boolean flag=true;//外部停止方式@Overridepublic  void run() {//买票while(flag){try {buy();} catch (InterruptedException e) {e.printStackTrace();}}}//synchronized 同步方法,锁的是thisprivate synchronized void buy() throws InterruptedException {//判断是否有票if(ticketNums<=0){flag=false;return;}//模拟延时Thread.sleep(100);//买票System.out.println(Thread.currentThread().getName()+"拿到"+ticketNums--);}
}
package com.zeng.syn;import java.util.ArrayList;//线程不安全的集合
public class TestUnsafeList {public static void main(String[] args) {ArrayList<String> list = new ArrayList<>();for (int i = 0; i < 10000; i++) {new Thread(()->{synchronized (list){list.add(Thread.currentThread().getName());}}).start();}try {Thread.sleep(3000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(list.size());}
}
package com.zeng.syn;import java.util.concurrent.CopyOnWriteArrayList;
//测试JUC安全类型的集合
public class TestJUc {public static void main(String[] args) {CopyOnWriteArrayList<String> list = new CopyOnWriteArrayList<>();for (int i = 0; i < 1000; i++) {new Thread(()->{list.add(Thread.currentThread().getName());});}try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(list.size());}
}

死锁

  • 产生死锁的四个必要条件
    • 互斥条件:一个资源每次只能被一个进程使用。
    • 请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。
    • 不剥夺条件:进程已获得的资源,在未使用完之前,不能强行剥夺。
    • 循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。
package com.zeng.thread;
//死锁:多个线程互相抱着对方的资源,然后形成僵持。
public class DeadLock {public static void main(String[] args) {Makeup s1 = new Makeup(0, "灰姑娘");Makeup s2 = new Makeup(0, "白雪公主");s1.start();s2.start();}
}
//口红
class Lipstick{}//镜子
class Mirror{}
class Makeup extends Thread{//需要的资源只有一份,用static来保证只有一份static Lipstick lipstick=new Lipstick();static Mirror mirror=new Mirror();int choice;//选择String girlName;//使用化妆品的人Makeup(int choice,String girlName){this.choice=choice;this.girlName=girlName;}@Overridepublic void run() {//化妆try {makeup();} catch (InterruptedException e) {e.printStackTrace();}}//化妆,互相持有对方的锁,就是需要拿到对方的资源private void makeup() throws InterruptedException {if(choice==0){synchronized (lipstick){//获得口红的锁System.out.println(this.girlName+"获得口红的锁");Thread.sleep(1000);
//                synchronized (mirror){//一秒钟获得镜子
//                    System.out.println(this.girlName+"获得镜子的锁");
//                }}synchronized (mirror){//一秒钟获得镜子System.out.println(this.girlName+"获得镜子的锁");}}else{synchronized (mirror){//一秒钟获得镜子System.out.println(this.girlName+"获得镜子的锁");Thread.sleep(1000);
//                synchronized (lipstick){//获得口红的锁
//                    System.out.println(this.girlName+"获得口红的锁");
//                }}synchronized (lipstick){//获得口红的锁System.out.println(this.girlName+"获得口红的锁");}}}
}

Lock锁

  • Lock是显式锁(手动开启和关闭锁,别忘记关闭锁)synchronized是隐式锁,出了作用域自动释放。
  • Lock只有代码块锁,synchronized有代码块锁和方法锁
  • 使用Lock锁,JVM花费较少的时间来调度线程,性能更好。并且具有更好的扩展性(提供更多的子类)
  • 优先使用顺序
    • Lock>同步代码块(已经进入方法体,分配了相应资源)>同步方法(在方法体之外)
package com.zeng.thread;import java.util.concurrent.locks.ReentrantLock;public class TestLock {public static void main(String[] args) {TestLock2 testLock2 = new TestLock2();new Thread(testLock2).start();new Thread(testLock2).start();new Thread(testLock2).start();}
}class TestLock2 implements Runnable{int ticketNums=10;//定义Lock锁private final ReentrantLock lock=new ReentrantLock();@Overridepublic void run() {while(true){try {lock.lock();if(ticketNums>0){try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(ticketNums--);}else{break;}} finally {//解锁lock.unlock();//如果同步代码有异常,要将unlock()写入finally语句块}}}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/309213.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Java,C++四舍五入

如果要进行四舍五入&#xff0c;可以对浮点数加上0.5再强制转型&#xff1a; package HomeTest01;public class Main {public static void main(String[] args){double a 0.6;System.out.println((int)(a0.5));double b 0.4;System.out.println((int)(b0.5));}}C也同理&…

利用Azure Functions和k8s构建Serverless计算平台

题记&#xff1a;昨晚在一个技术社区直播分享了“利用Azure Functions和k8s构建Serverless计算平台”这一话题。整个分享分为4个部分&#xff1a;Serverless概念的介绍、Azure Functions的简单介绍、k8s和KEDA的介绍和最后的演示。ServerlessServerless其实包含了两种概念&…

Java格式化输出

Java还提供了格式化输出的功能。为什么要格式化输出&#xff1f;因为计算机表示的数据不一定适合人来阅读。 如果要把数据显示成我们期望的格式&#xff0c;就需要使用格式化输出的功能。格式化输出使用System.out.printf()&#xff0c;通过使用占位符%?&#xff0c;printf()…

基于 abp vNext 和 .NET Core 开发博客项目 - 终结篇之发布项目

系列文章使用 abp cli 搭建项目给项目瘦身&#xff0c;让它跑起来完善与美化&#xff0c;Swagger登场数据访问和代码优先自定义仓储之增删改查统一规范API&#xff0c;包装返回模型再说Swagger&#xff0c;分组、描述、小绿锁接入GitHub&#xff0c;用JWT保护你的API异常处理和…

并发协作模型“生产者/消费者模式“

java提供了几个方法解决线程之间的通信问题 方法名作用wait()表示线程一直等待&#xff0c;直到其他线程通知&#xff0c;与sleep不同&#xff0c;会释放锁wait(long timeout)指定等待的毫秒数notify唤醒一个处于等待状态的线程notifyAll()唤醒同一个对象上所有调用wait()方法…

使用线程池

JDk5.0起提供了线程池相关的API&#xff1a;ExecutorService和ExecutorsExectorService&#xff1a;真正的线程池接口。常见的子类ThreadPoolExecutor void execute(Runnable command):执行任务/命令&#xff0c;没有返回值&#xff0c;一般用来执行RunnableFuturesubmit(Calla…

对 JsonConvert 的认识太肤浅了,终于还是遇到了问题

一&#xff1a;背景1. 讲故事在开始本文之前&#xff0c;真的好想做个问卷调查&#xff0c;到底有多少人和我一样&#xff0c;对 JsonConvert 的认识只局限在 SerializeObject 和 DeserializeObject 这两个方法上(┬&#xff3f;┬), 这样我也好结伴同行&#xff0c;不再孤单落…

Java继承-子类不可以继承父类的构造方法

子类不可以继承父类的构造方法&#xff0c;只可以调用父类的构造方法。 子类中所有的构造函数都会默认访问父类中的空参数构造函数&#xff0c;这是因为子类的构造函数内第一行都有默认的super&#xff08;&#xff09;语句。 super&#xff08;&#xff09;表示子类在初始化…

.Net微服务实战之DevOps篇

技术只是基础该系列的两篇文章《.Net微服务实战之技术选型篇》和《.Net微服务实战之技术架构分层篇》都是以技术角度出发描述微服务架构的实施。如果技术选型篇叙述的是工具&#xff0c;那么架构分层篇讲的就是技巧&#xff0c;而本篇要讨论的就是原则。一直以来我会给身边向我…

阿里云挑战赛

文章目录第一题题目&#xff1a;题解&#xff1a;第二题题目题解第三题题目题解第四题题目&#xff1a;题解第五题题目题解第六题题目题解第七题题目&#xff1a;题解第八题题目&#xff1a;题解;题解赛后出第一题 题目&#xff1a; 【单选】filter 方法意图过滤传入的订单列…

使用C#编写STM32对接物联网平台IoTSharp发送遥测数据

在之前的文章中&#xff0c; 我们阐述了如何用C#在STM32上写第一个Hello world &#xff0c; 有朋友抱怨国内介绍文章&#xff0c; 都是一个 Hello world &#xff0c; 然后再也没有音讯&#xff0c; 写到这里我想提一下我的初心&#xff0c; 那就是告诉所有人C#无所不能&…

JavaMVC之JSON

JSON 8.1、什么是JSON&#xff1f; JSON(JavaScript Object Notation, JS 对象标记) 是一种轻量级的数据交换格式&#xff0c;目前使用特别广泛。采用完全独立于编程语言的文本格式来存储和表示数据。简洁和清晰的层次结构使得 JSON 成为理想的数据交换语言。易于人阅读和编写…

Java源文件声明规则

源文件声明规则: 当在一个源文件中定义多个类&#xff0c;并且还有import语句和package语句时&#xff0c;要特别注意这些规则。 一个源文件中只能有一个 public 类 一个源文件可以有多个非 public 类 源文件的名称应该和 public 类的类名保持一致。例如&#xff1a;源文件中…

Java内置数据类型

内置数据类型 Java语言提供了八种基本类型。六种数字类型&#xff08;四个整数型&#xff0c;两个浮点型&#xff09;&#xff0c;一种字符类型&#xff0c;还有一种布尔型。 byte&#xff1a; byte 数据类型是8位、有符号的&#xff0c;以二进制补码表示的整数&#xff1b; …

龙芯团队完成CoreCLR MIPS64移植,在github开源

国产龙芯的软件生态之中.NET不会缺席&#xff0c;毕竟 C# 与 .NetCore/Mono 也是全球几大主流的编程语言和运行平台之一&#xff0c;最近一段时间听到太多的鼓吹政务领域不支持.NET&#xff0c; 大家都明白这是某些人为了自己的利益打压使用.NET技术的公司&#xff0c;我今天写…

alibaba实习生代码大赛

文章目录题目Explanation代码&#xff08;此代码排名13&#xff0c;前十名有奖233333&#xff09;结果题目 在一个风雨交加的周末下午&#xff0c;大部分人都很不开心&#xff0c;因为出行不变&#xff0c;计划的娱乐活动都取消了&#xff0c;但菜鸟快递员小王却异常高兴&…

Java自动类型转换和强制类型转换(隐含)

自动类型转换 整型、实型&#xff08;常量&#xff09;、字符型数据可以混合运算。 运算中&#xff0c;不同类型的数据先转化为同一类型&#xff0c;然后进行运算。 转换从低级到高级。 低 ------------------------------------> 高 byte,short,char—> int —> …

来谈一谈专注力的真相

这是头哥侃码的第205篇原创在日常生活&#xff08;或工作&#xff09;中&#xff0c;你有没有遇上过这样的情况&#xff1f;比如你正在跟小伙伴讨论一个技术方案&#xff0c;聊着聊着&#xff0c;突然小A脑袋一抽筋&#xff0c;问你&#xff1a;“老大&#xff0c;咱们这周五晚…

成功陷阱有感

分享一下看到的关于成功陷阱的段落&#xff0c;关于成功陷阱&#xff0c;主要是最近面试字节跳动时&#xff0c;面试官向我推荐的&#xff0c;虽然也没有找到名叫《成功陷阱》的书&#xff08;后来发现书名应该是叫《能力陷阱》&#xff09;&#xff0c;但看了一些文章 最近听了…