
线程(中)
发布日期:2021-05-06 03:20:44
浏览次数:19
分类:技术文章
本文共 7284 字,大约阅读时间需要 24 分钟。
线程的状态
start();启动线程 就绪状态(等待CPU的加载)
当线程获得了CPU的执行权,进入到运行状态
当线程失去CPU执行权(因为CPU需要轮流执行其他线程),进入待就绪状态
当线程中所有任务执行完以后,进入死亡状态
yield();线程主动让步
sleep();让线程休眠指定时间,进入阻塞状态
t.join();线程合并,等待t进程执行完后,其他进程再执行
stop();强制让线程销毁
public class ThreadDemo extends Thread{ @Override public void run() { for (int i = 0; i <1000 ; i++) { /*if (i%5==0){ Thread.yield();//线程主动让步 }*/ /* try { Thread.sleep(1000);//让线程休眠指定时间,进入阻塞状态 } catch (InterruptedException e) { e.printStackTrace(); }*/ System.out.println(Thread.currentThread().getName()+":"+i); } }}
public class Test { public static void main(String[] args) { ThreadDemo threadDemo = new ThreadDemo(); threadDemo.setName("线程1"); threadDemo.start();//启动线程 就绪状态(等待CPU加载) // 当线程获得了CPU的执行权 ,进入到运行状态 //当线程失去CPU执行权(因为CPU还要轮流执行其他线程),进入就绪状态 //当线程中所有任务执行完以后,进入死亡状态 /* try { threadDemo.join();//线程合并,等待threadDemo线程执行完后,其他线程执行 } catch (InterruptedException e) { e.printStackTrace(); }*/ //threadDemo.stop();//强制让线程销毁 ThreadDemo threadDemo2 = new ThreadDemo(); threadDemo2.setName("线程2"); threadDemo2.start();//启动线程 //threadDemo2.stop();//强制让线程销毁 }}
守护线程
是一种特殊的线程
当把一个线程设置为守护线程时,守护线程需要等所有得非守护线程执行完结束后,才会销毁
t.setDaemon(true);将线程设置为守护线程
JVM中垃圾回收器就是一个典型的守护线程
public class ThreadDemo extends Thread{ @Override public void run() { while (true){ System.out.println("我是守护线程"); } }}public class Test { public static void main(String[] args) { ThreadDemo threadDemo = new ThreadDemo(); threadDemo.setDaemon(true);//将线程设置为守护线程 threadDemo.start();//启动线程 for (int i = 0; i < 1000; i++) { System.out.println("我是用户线程"); } }}
线程的同步
并行:多个CPU同时执行多个任务
并发:一个CPU同时执行多个任务
前提:
1.必须是多线程
2.多线程访问同一个共享资源
同步机制:线程排队+锁
static 变量 随着类的加载而加载,生命周期长
非static 变量 生命周期与对象相同
典型案例:买票
票数是固定的,买票的窗口有多个,就有多个线程同时访问同一资源
使用synchronize修饰
通过两种创建线程的方法实现功能
一.继承Thread类
1.synchronize修饰同步代码块
public class VoteDemo extends Thread { static int votes = 10;//多个线程访问共享资源 static Object obj = new Object();//创建唯一的锁 @Override public void run() { //while循环一直出票 while (true) { //为需要同步的代码,用同步代码快修饰,多个线程只有一把锁,谁先拿到谁就用 //当持有锁的线程把同步代码中的内容执行完以后,离开同步代码快,会自动释放锁 synchronized (obj){ if (votes > 0) { System.out.println(Thread.currentThread().getName() + ":" + votes); votes--; } else if (votes <= 0) { break; } } } }
2.用synchronized修饰方法,此方法为同步方法
public class VoteDemo extends Thread { static int votes = 10;//多个线程访问共享资源 @Override public void run() { while (true) { if (votes > 0) { vote(); } else { break; } } } //用synchronized修饰方法,此方法为同步方法 //synchronized修饰方式时,锁对象默认为this,多个线程就有多把锁 public static synchronized void vote() { if (votes > 0) { System.out.println(Thread.currentThread().getName() + ":" + votes); votes--; } }}
测试类
public class Test { public static void main(String[] args) { VoteDemo voteDemo = new VoteDemo(); voteDemo.setName("窗口1"); voteDemo.start(); VoteDemo voteDemo2 = new VoteDemo(); voteDemo2.setName("窗口2"); voteDemo2.start(); }}
二.实现Runnable类
1.synchronize修饰同步代码块
public class VoteDemo implements Runnable { int votes = 10; Object obj = new Object(); //修饰同步内容 @Override public void run() { while (true) { synchronized (obj){ if (votes > 0) { System.out.println(Thread.currentThread().getName() + ":" + votes); votes--; } else if (votes <= 0) { break; } } } }}
2.用synchronized修饰方法,此方法为同步方法
public class VoteDemo implements Runnable { int votes = 10; Object obj = new Object(); @Override public void run() { while (true) { if (votes > 0) { Vote(); } else { break; } } } //用synchronize修饰方法,此方法为同步方法 //synchronize修饰方法时,锁对象默认为this,只创建一个线程任务对象,this只有一个 public synchronized void Vote() { if (votes > 0) { System.out.println(Thread.currentThread().getName() + ":" + votes); votes--; } }}
测试类
public class Test { public static void main(String[] args) { VoteDemo voteDemo = new VoteDemo(); Thread thread1 = new Thread(voteDemo); Thread thread2 = new Thread(voteDemo); thread1.setName("窗口1"); thread2.setName("窗口2"); thread1.start(); thread2.start(); }}
线程死锁
当线程持有对方线程中需要的锁时,会出现死锁现象
public class DieLock extends Thread { static Object objA = new Object(); static Object objB = new Object(); boolean flag; public DieLock(boolean flag) { this.flag = flag; } @Override public void run() { if (flag){ synchronized (objA){ System.out.println("if objA");//objA这把锁已经被使用 synchronized (objB){ //此时只能等待下面释放objB锁 System.out.println("if objB"); } } }else{ synchronized (objB){ System.out.println("else objB");//objB这把锁也被使用 synchronized (objA){ //此时等待上面释放objA锁 System.out.println("else objA"); } } } }}
public class Test { public static void main(String[] args) { DieLock t1= new DieLock(true); DieLock t2= new DieLock(false); t1.start(); t2.start(); }}
运行结果:
死锁出现不会报错,不会提示,只是等待.
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DZyhn87e-1611997903680)(C:\Users\17509\AppData\Roaming\Typora\typora-user-images\1611204001419.png)]
Lock方式的加锁
JDK5之后使用Lock方式显示的加锁,释放锁
Lock是显式锁(手动开启和关闭锁,别忘记关闭锁), 实现类ReentrantLock
synchronized是隐式锁,出了作用域自动释放Lock只有代码块锁
synchronized 有代码块锁,方法
import java.util.concurrent.locks.Lock;import java.util.concurrent.locks.ReentrantLock;public class VoteDemo extends Thread { static int num = 10; static Lock lock = new ReentrantLock();//创建锁对象 @Override public void run() { while(true){ try { lock.lock();//获得锁,加锁 Thread.sleep(100); if(num>0){ System.out.println(num); num--; }else{ break; } lock.unlock();//释放锁 }catch (Exception e){ e.printStackTrace(); lock.unlock();//释放锁 } } }}
public class Test { public static void main(String[] args) { VoteDemo voteDemo = new VoteDemo(); voteDemo.setName("窗口1"); voteDemo.start(); VoteDemo voteDemo2 = new VoteDemo(); voteDemo2.setName("窗口2"); voteDemo2.start(); }}
发表评论
最新留言
感谢大佬
[***.8.128.20]2025年04月08日 23时47分01秒
关于作者

喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!
推荐文章
使用 github 搜索
2019-03-01
java有包名的类访问没有包名的类
2019-03-01
整型关键字的散列映射
2019-03-03
多位水仙花数-python(出现运行超时?不妨用减法计算)
2019-03-03
地下迷宫探索(后两个测试点无法通过?这里有你想要的答案)
2019-03-03
小白看完都会了!阿里云大师深入拆解Java虚拟机,看完这一篇你就懂了
2019-03-03
VBA之正则表达式(19)-- 相对引用转绝对引用
2019-03-03
巧用VBA统一数字单位
2019-03-03
Transpose实现数组行列转置的限制
2019-03-03
golang中interface的一些语法缺陷的改进
2019-03-03
vue-router路由 学习笔记
2019-03-03
【数据库】第七章课后题
2019-03-03
第四章 串、数组和广义表 —— BF算法和KMP算法
2019-03-03
[选拔赛1]花园(矩阵快速幂),JM的月亮神树(最短路),保护出题人(斜率优化)
2019-03-03
DLA:一种深度网络特征融合方法
2019-03-03
leetcode114(二叉树展开为链表)
2019-03-03
java —— static 关键字
2019-03-03
在 Python 调试过程中设置不中断的断点 | Linux 中国
2019-03-03
使用开源可视化工具来理解你的 Python 代码 | Linux 中国
2019-03-03
硬核观察 | 有人在比特币骗局中损失了 10 个比特币
2019-03-03