当前位置: 首页 > news >正文

Java基础 10.8

1.线程终止

基本说明

  1. 当线程完成任务后,会自动退出
  2. 还可以通过使用变量来控制run方法退出的方式停止线程,即通知方式

应用案例

public class ThreadExit_ {public static void main(String[] args) throws InterruptedException {T t1 = new T();t1.start();//如果希望main线程去控制t1 线程的终止, 必须可以修改 loop//让t1 退出run方法,从而终止 t1线程 -> 通知方式//让主线程休眠 10 秒,再通知 t1线程退出System.out.println("main线程休眠10s...");Thread.sleep(10 * 1000);t1.setLoop(false);}
}class T extends Thread {private int count = 0;//设置一个控制变量private boolean loop = true;@Overridepublic void run() {while (loop) {try {Thread.sleep(50);// 让当前线程休眠50ms} catch (InterruptedException e) {e.printStackTrace();}System.out.println("T 运行中...." + (++count));}}public void setLoop(boolean loop) {this.loop = loop;}
}

2.线程常用方法

方法第一组

注意事项和细节

  1. start 底层会创建新的线程,调用run,run就是一个简单的方法调用,不会启动新线程
  2. 线程优先级的范围
  3. interrupt,中断线程,但并没有真正的结束线程。所以一般用于中断正在休眠线程
  4. sleep:线程的静态方法,使当前线程休眠

应用案例

public class ThreadMethod01 {public static void main(String[] args) throws InterruptedException {//测试相关的方法T t = new T();t.setName("a");t.setPriority(Thread.MIN_PRIORITY);//1t.start();//启动子线程//主线程打印5 hi ,然后我就中断 子线程的休眠for(int i = 0; i < 5; i++) {Thread.sleep(1000);System.out.println("hi " + i);}System.out.println(t.getName() + " 线程的优先级 =" + t.getPriority());//1t.interrupt();//当执行到这里,就会中断 t线程的休眠.}
}class T extends Thread { //自定义的线程类@Overridepublic void run() {while (true) {for (int i = 0; i < 100; i++) {//Thread.currentThread().getName() 获取当前线程的名称System.out.println(Thread.currentThread().getName() + "  吃包子~~~~" + i);}try {System.out.println(Thread.currentThread().getName() + " 休眠中~~~");Thread.sleep(20000);//20秒} catch (InterruptedException e) {//当该线程执行到一个interrupt 方法时,就会catch 一个 异常, 可以加入自己的业务代码//InterruptedException 是捕获到一个中断异常.System.out.println(Thread.currentThread().getName() + "被 interrupt了");}}}
}

方法第二组

应用案例

public class ThreadMethod02 {public static void main(String[] args) throws InterruptedException {T2 t2 = new T2();t2.start();for(int i = 1; i <= 20; i++) {Thread.sleep(1000);System.out.println("主线程(小弟) 吃了 " + i  + " 包子");if(i == 5) {System.out.println("主线程(小弟) 让 子线程(老大) 先吃");//join, 线程插队//t2.join();// 这里相当于让t2 线程先执行完毕Thread.yield();//礼让,不一定成功..System.out.println("线程(老大) 吃完了 主线程(小弟) 接着吃..");}}}
}class T2 extends Thread {@Overridepublic void run() {for (int i = 1; i <= 20; i++) {try {Thread.sleep(1000);//休眠1秒} catch (InterruptedException e) {e.printStackTrace();}System.out.println("子线程(老大) 吃了 " + i +  " 包子");}}
}

用户线程和守护线程

  • 用户线程:也叫工作线程,当线程的任务执行完或通知方式结束
  • 守护线程:一般是为工作线程服务的,当所有的用户线程结束,守护线程自动结束
  • 常见的守护线程:垃圾回收机制

应用案例

public class ThreadMethod03 {public static void main(String[] args) throws InterruptedException {MyDaemonThread myDaemonThread = new MyDaemonThread();//如果我们希望当main线程结束后,子线程自动结束//,只需将子线程设为守护线程即可myDaemonThread.setDaemon(true);myDaemonThread.start();for( int i = 1; i <= 10; i++) {//main线程System.out.println("宝强在辛苦的工作...");Thread.sleep(1000);}}
}class MyDaemonThread extends Thread {public void run() {for (; ; ) {//无限循环try {Thread.sleep(1000);//休眠1000毫秒} catch (InterruptedException e) {e.printStackTrace();}System.out.println("马蓉和宋喆快乐聊天,哈哈哈~~~");}}
}

3.线程生命周期

线程状态转换图

程序查看线程状态

public class ThreadState_ {public static void main(String[] args) throws InterruptedException {T t = new T();System.out.println(t.getName() + " 状态 " + t.getState());t.start();while (Thread.State.TERMINATED != t.getState()) {System.out.println(t.getName() + " 状态 " + t.getState());Thread.sleep(500);}System.out.println(t.getName() + " 状态 " + t.getState());}
}class T extends Thread {@Overridepublic void run() {while (true) {for (int i = 0; i < 10; i++) {System.out.println("hi " + i);try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}break;}}
}

4.线程的同步

 Synchronized

线程同步机制

  1. 在多线程编程,一些敏感数据不允许被多个线程同时访问,此时就使用同步访问技术,保证数据在任何同一时刻最多有一个线程访问,以保证数据的完整性
  2. 也可以这里理解:线程同步,即当有一个线程在对内存进行操作时,其他线程都不可以对这个内存地址进行操作,直到该线程完成操作,其他线程才能对该内存地址进行操作

同步具体方法

1. 同步代码块
synchronized(对象){//得到对象的锁,才能操作同步代码
//需要被同步代码;
}2. synchronized还可以放在方法声明中,表示整个方法-为同步方法
public synchronized void m (String name){
//需要被同步的代码
}

5.互斥锁

基本介绍

  1. Java语言中,引入了对象互斥锁的概念,来保证共享数据操作的完整性
  2. 每个对象都对应于一个可称为“互斥锁”的标记,这个标记用来保证在任一时刻,只能有一个线程访问该对象
  3. 关键字synchronized 来与对象的互斥锁联系。当某个对象用synchronized修饰时,表明该对象在任一时刻只能由一个线程访问
  4. 同步的局限性:导致程序的执行效率要降低
  5. 同步方法(非静态的)的锁可以是this,也可以是其他对象(要求是同一个对象)
  6. 同步方法(静态的)的锁为当前类本身

案例

public class SellTicket {public static void main(String[] args) {//测试
//        SellTicket01 sellTicket01 = new SellTicket01();
//        SellTicket01 sellTicket02 = new SellTicket01();
//        SellTicket01 sellTicket03 = new SellTicket01();
//
//        //这里我们会出现超卖..
//        sellTicket01.start();//启动售票线程
//        sellTicket02.start();//启动售票线程
//        sellTicket03.start();//启动售票线程System.out.println("===使用实现接口方式来售票=====");SellTicket02 sellTicket02 = new SellTicket02();new Thread(sellTicket02).start();//第1个线程-窗口new Thread(sellTicket02).start();//第2个线程-窗口new Thread(sellTicket02).start();//第3个线程-窗口}
}//使用Thread方式class SellTicket01 extends Thread {private static int ticketNum = 100;//让多个线程共享 ticketNum@Overridepublic void run() {while (true) {if (ticketNum <= 0) {System.out.println("售票结束...");break;}//休眠50毫秒, 模拟try {Thread.sleep(50);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("窗口 " + Thread.currentThread().getName() + " 售出一张票"+ " 剩余票数=" + (--ticketNum));}}
}//实现接口方式
class SellTicket02 implements Runnable {private int ticketNum = 100;//让多个线程共享 ticketNum@Overridepublic void run() {while (true) {if (ticketNum <= 0) {System.out.println("售票结束...");break;}//休眠50毫秒, 模拟try {Thread.sleep(50);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("窗口 " + Thread.currentThread().getName() + " 售出一张票"+ " 剩余票数=" + (--ticketNum));//1 - 0 - -1  - -2}}
}

注意事项和细节

  • 同步方法如果没有使用static修饰:默认锁对象为this
  • 如果方法使用static修饰,默认锁对象:当前类.class

实现的落地步骤

  1. 需要先分析上锁的代码
  2. 选择同步代码块或同步方法
  3. 要求多个线程的锁对象为同一个即可

6.线程的死锁

基本介绍

多个线程都占用了对方锁资源,但不肯相让,导致了死锁,在编程是一定要避免死锁发生

案例

public class DeadLock_ {public static void main(String[] args) {//模拟死锁现象DeadLockDemo A = new DeadLockDemo(true);A.setName("A线程");DeadLockDemo B = new DeadLockDemo(false);B.setName("B线程");A.start();B.start();}
}//线程
class DeadLockDemo extends Thread {static Object o1 = new Object();// 保证多线程,共享一个对象,这里使用staticstatic Object o2 = new Object();boolean flag;public DeadLockDemo(boolean flag) {//构造器this.flag = flag;}@Overridepublic void run() {//下面业务逻辑的分析//1. 如果flag 为 T, 线程A 就会先得到/持有 o1 对象锁, 然后尝试去获取 o2 对象锁//2. 如果线程A 得不到 o2 对象锁,就会Blocked//3. 如果flag 为 F, 线程B 就会先得到/持有 o2 对象锁, 然后尝试去获取 o1 对象锁//4. 如果线程B 得不到 o1 对象锁,就会Blockedif (flag) {synchronized (o1) {//对象互斥锁, 下面就是同步代码System.out.println(Thread.currentThread().getName() + " 进入1");synchronized (o2) { // 这里获得li对象的监视权System.out.println(Thread.currentThread().getName() + " 进入2");}}} else {synchronized (o2) {System.out.println(Thread.currentThread().getName() + " 进入3");synchronized (o1) { // 这里获得li对象的监视权System.out.println(Thread.currentThread().getName() + " 进入4");}}}}
}

7.释放锁

下列操作释放锁

  1. 当前线程的同步方法、同步代码块执行结束 案例:上厕所,完事出来
  2. 当前线程在同步代码块、同步方法中遇到breakreturn 案例:没有正常的完事,经理叫他修改bug,不得已出来
  3. 当前线程在同步代码块、同步方法中出现了未处理的Error或Exception,导致异常结束 案例:没有正常的完事,发现忘带纸,不得已出来
  4. 当前线程在同步代码块、同步方法中执行了线程对象的wait()方法,当前线程暂停,并释放锁。 案例:没有正常完事,觉得需要酝酿下,所以出来等会再进去

下列操作不会释放锁

  1. 线程执行同步代码块或同步方法时,程序调用Thread.sleep()、Thread.yield()方法暂停当前线程的执行不会释放锁 案例:上厕所,太困了,在坑位上眯了一会
  2. 线程执行同步代码块时,其他线程调用了该线程的suspend()方法将该线程挂起,该线程不会释放锁。提示:应尽量避免使用suspend()和resume()来控制线程,方法不再推荐使用
http://www.dtcms.com/a/458594.html

相关文章:

  • 长湖南营销型网站简单网站建设公司
  • 计算机基础——浏览器、算法、计算机原理和编译原理等
  • 网站制作企业有哪些下页
  • 企业做外贸网站常用术语通江移动网站建设
  • vultr做网站广东软件公司排名
  • [1]python爬虫入门,爬取豆瓣电影top250实践
  • 学习网站开发体会与感想wordpress多语言插件:qtranslate
  • 辽源市网站建设html怎么制作网页
  • 旅游网站建设的目标蓝天下品牌运营业务展示
  • 网站死循环青岛网红打卡景点
  • 域名过期做的网站怎么办门户网站建设与推广方案
  • 文档做网站闵行营销型网站制作
  • 网页设计报告模板免费wordpress安装后优化
  • 重庆制作网站公司简介网上商城运营推广方案
  • 网站代码怎么打开青岛制作公司网站
  • 适合女生做的网站主题做网站销售一个星期的计划
  • 郑州一凡网站建设简易手机站
  • 软件的基础原理
  • 临安城市建设公司网站丽水山耕品牌建设网站
  • 部门网站建设工作总结西安seo主管
  • 淮安市建设局网站首页中国电建成都设计院
  • Java--文件操作和IO
  • 收费的网站怎么做的哪个小说网站可以做封面
  • Kotlin when 用法完整分享
  • 巩义网站建设汕头市网络推广报价
  • 有哪些网站建设工作推广文案怎么写
  • 深圳宝安建网站动漫制作专业要多少分
  • Python爬虫优化实战:高效稳定爬图技巧
  • wordpress网站更新合水网站建设
  • 获取印度尼西亚股票数据API完全指南