1.线程生命周期

1.新建
2.就绪
3.运行
4.阻塞
5.死亡

1.新建->就绪
start()方法

2.就绪->运行
获取cpu执行权

3.运行->就绪
失去cpu执行权
yield()方法

4.运行->阻塞
sleep(long time)
suspend() 已弃用
join()
等待同步锁
wait()

5.阻塞->运行
sleep结束
jion对应的线程结束
resume() 对应于suspend 已弃用
获取同步锁
notify() notifyAll()

6.运行->死亡
run()方法结束
stop()方法
出现error或者exception

2.线程安全解决方式一:同步代码块

sychronized(同步监视器,即锁){
//操作共享数据的代码
}

锁的要求:任意一个对象都可以充当锁,但是所有线程必须共用一个锁

package com.exer;/*** @author ym* @create 2022-01-24 20:45* @description*/
public class TicketDemo1 {public static void main(String[] args) {MyThread myThread = new MyThread();Thread thread1 = new Thread(myThread);Thread thread2 = new Thread(myThread);Thread thread3 = new Thread(myThread);thread1.start();thread2.start();thread3.start();}
}class MyThread implements Runnable {public int tickets = 100;public Object obj = new Object();/*** When an object implementing interface <code>Runnable</code> is used* to create a thread, starting the thread causes the object's* <code>run</code> method to be called in that separately executing* thread.* <p>* The general contract of the method <code>run</code> is that it may* take any action whatsoever.** @see Thread#run()*/@Overridepublic void run() {while (true) {//此处加上了同步代码块synchronized (obj) {if (tickets > 0) {System.out.println(Thread.currentThread().getName() + "\t" + tickets);tickets--;} else {break;}}}}
}
package com.exer;/*** @author ym* @create 2022-01-24 20:12* @description 三个窗口卖票问题*/
public class TicketDemo {public static int tickets = 100;public static void main(String[] args) {TicketSell ticketSell1 = new TicketSell();TicketSell ticketSell2 = new TicketSell();TicketSell ticketSell3 = new TicketSell();ticketSell1.start();ticketSell2.start();ticketSell3.start();}
}class TicketSell extends Thread {@Overridepublic void run() {while (true) {synchronized (TicketSell.class) {if (TicketDemo.tickets > 0) {TicketDemo.tickets--;System.out.println(TicketDemo.tickets + "\t" + getName());} else {break;}}}}
}

3.线程安全解决方式二:同步方法

如果某一方法全部涉及处理共享数据,则可将此方法设置为同步方法,但是需注意,实现runnable接口方法创建的线程与继承Thread方法在同步方法上略有不同
实现runnable()接口方法创建的线程可以直接同步,但是继承Thread()方法实现的线程在同步方法时需要设置为static,原理:
同步方法也是需要同步监视器的,只不过不需显式指明。如果是非static方法,则同步方法的同步监视器是对象,如果是static方法,则同步方法的同步监视器是类

package com.exer2;/*** @author ym* @create 2022-01-24 20:12* @description 三个窗口卖票问题*/
public class TicketDemo {public static int tickets = 100;public static void main(String[] args) {TicketSell ticketSell1 = new TicketSell();TicketSell ticketSell2 = new TicketSell();TicketSell ticketSell3 = new TicketSell();ticketSell1.start();ticketSell2.start();ticketSell3.start();}
}class TicketSell extends Thread {@Overridepublic void run() {while (true) {show();}}public static synchronized void show() {if (TicketDemo.tickets > 0) {TicketDemo.tickets--;System.out.println(TicketDemo.tickets + "\t" + Thread.currentThread().getName());}}
}
package com.exer2;/*** @author ym* @create 2022-01-24 20:45* @description*/
public class TicketDemo1 {public static void main(String[] args) {MyThread myThread = new MyThread();Thread thread1 = new Thread(myThread);Thread thread2 = new Thread(myThread);Thread thread3 = new Thread(myThread);thread1.start();thread2.start();thread3.start();}
}class MyThread implements Runnable {public int tickets = 100;public Object obj = new Object();/*** When an object implementing interface <code>Runnable</code> is used* to create a thread, starting the thread causes the object's* <code>run</code> method to be called in that separately executing* thread.* <p>* The general contract of the method <code>run</code> is that it may* take any action whatsoever.** @see Thread#run()*/@Overridepublic void run() {while (true) {show();}}public synchronized void show() {if (tickets > 0) {System.out.println(Thread.currentThread().getName() + "\t" + tickets);tickets--;}}
}

4.手写一个线程安全的效率较高的懒汉式单例模式

/*** @author ym* @create 2022-01-25 11:10* @description 线程安全的效率较高的单例模式之懒汉式*/
public class Sluggard {private Sluggard() {}public static Sluggard instanse = null;public Sluggard getInstanse() {if (instanse == null) {//如果是空,那么在下面同步代码块里进行操作,// 如果不是空,不需同步代码块,直接返回已经生成好了的实例即可synchronized (Sluggard.class) {instanse = new Sluggard();}}return instanse;}
}

5.线程的死锁问题

它的本质是由于同步机制引起的,不同的线程占用对方需要的同步资源不放弃,都在等待对方放弃自己需要的同步资源
解决方法:
1.专门的算法、原则
2.尽量减少同步资源的定义
3.尽量避免嵌套同步

6.线程安全解决方式三:lock方法

此方法有个疑惑,写在前面,我在测试用继承Thread方法实现的线程时,并未实现同步效果,目前未想出原因,将代码也贴在下面

package com.lock;import java.util.concurrent.locks.ReentrantLock;/*** @author ym* @create 2022-01-24 20:12* @description 三个窗口卖票问题*/
public class TicketDemo {public static int tickets = 100;public static void main(String[] args) {TicketSell ticketSell1 = new TicketSell();TicketSell ticketSell2 = new TicketSell();TicketSell ticketSell3 = new TicketSell();ticketSell1.start();ticketSell2.start();ticketSell3.start();}
}class TicketSell extends Thread {//1.获取ReentrantLock对象,如果参数为true,则每个线程的机会是公平的private ReentrantLock lock = new ReentrantLock();@Overridepublic void run() {while (true) {try {//2.打开锁lock.lock();if (TicketDemo.tickets > 0) {TicketDemo.tickets--;System.out.println(TicketDemo.tickets + "\t" + Thread.currentThread().getName());} else {break;}} finally {//3.关闭锁lock.unlock();}}}}
package com.lock;import java.util.concurrent.locks.ReentrantLock;/*** @author ym* @create 2022-01-24 20:45* @description*/
public class TicketDemo1 {public static void main(String[] args) {MyThread myThread = new MyThread();Thread thread1 = new Thread(myThread);Thread thread2 = new Thread(myThread);Thread thread3 = new Thread(myThread);thread1.start();thread2.start();thread3.start();}
}class MyThread implements Runnable {public int tickets = 100;//    public Object obj = new Object();public ReentrantLock lock = new ReentrantLock();/*** When an object implementing interface <code>Runnable</code> is used* to create a thread, starting the thread causes the object's* <code>run</code> method to be called in that separately executing* thread.* <p>* The general contract of the method <code>run</code> is that it may* take any action whatsoever.** @see Thread#run()*/@Overridepublic void run() {while (true) {try {lock.lock();if (tickets > 0) {System.out.println(Thread.currentThread().getName() + "\t" + tickets);tickets--;} else {break;}} finally {lock.unlock();}}}//    public synchronized void show() {//
//    }
}

7.synchronized与lock的对比

1.lock是显式锁,需要手动开启和关闭锁,synchronized是隐式锁,出了作用域自动释放
2.lock只有代码块锁,synchronized有代码块锁和方法锁
3.lock锁可以使JVM更快地调度线程,性能更好

8.线程通信

常用:wait() notify() notifuAll()
注意:
1.这三个方法需要在同步方法或者同步代码块里调用
2.这三个方法的调用者是同步监视器
3.这三个方法定义在Object类中

9.wait() 与 sleep()的不同

1.两个方法的声明位置不同,一个在Object类,一个在Thread类
2.两个方法的调用要求不同,wait()只能在同步代码块或者同步方法调用,sleep()可以在任何场景调用
3.sleep()不会释放同步监视器,wait()会

10.消费者生产者问题

package com.produce_and_consume;/*** @author ym* @create 2022-01-25 17:59* @description 生产者消费者模型,店员随时判断,如果超过20个货物,让生产者暂停,如果少于0个货物,让生产者工作,消费者暂停*/
public class ClerkTest {public static void main(String[] args) {Clerk clerk = new Clerk();Producer producer = new Producer(clerk);Thread produce = new Thread(producer);produce.start();Consumer consumer = new Consumer(clerk);Thread consume = new Thread(consumer);consume.start();}
}class Clerk {//货物  初始数量为0public int goods = 0;/*** 生产者进行生产,需注意:* 1.如果生产超过1个货物,就开始提醒消费者开始消费* 2.如果少于20个货物,就开始生产* 3.如果多于20个货物,就暂停生产*/public synchronized void produce() {if (goods < 20) {goods++;System.out.println(Thread.currentThread().getName() + "开始生产第" + goods + "个商品");notify();} else {try {wait();} catch (InterruptedException e) {e.printStackTrace();}}}/*** 消费者进行消费,需注意:* 1.如果消费超过1个货物,就开始提醒生产者进行生产* 2.如果多于1个货物,就开始消费* 3.如果少于1个货物,就暂停消费*/public synchronized void consume() {if (goods > 0) {System.out.println(Thread.currentThread().getName() + "开始消费第" + goods + "个货物");goods--;notify();} else {try {wait();} catch (InterruptedException e) {e.printStackTrace();}}}}class Producer implements Runnable {private Clerk clerk;public Producer(Clerk clerk) {this.clerk = clerk;}/*** When an object implementing interface <code>Runnable</code> is used* to create a thread, starting the thread causes the object's* <code>run</code> method to be called in that separately executing* thread.* <p>* The general contract of the method <code>run</code> is that it may* take any action whatsoever.** @see Thread#run()*/@Overridepublic void run() {System.out.println("生产者开始生产产品");while (true) {try {Thread.sleep(100);} catch (InterruptedException e) {e.printStackTrace();}clerk.produce();}}
}class Consumer implements Runnable {private Clerk clerk;public Consumer(Clerk clerk) {this.clerk = clerk;}/*** When an object implementing interface <code>Runnable</code> is used* to create a thread, starting the thread causes the object's* <code>run</code> method to be called in that separately executing* thread.* <p>* The general contract of the method <code>run</code> is that it may* take any action whatsoever.** @see Thread#run()*/@Overridepublic void run() {System.out.println("消费者开始消费产品");while (true) {try {Thread.sleep(100);} catch (InterruptedException e) {e.printStackTrace();}clerk.consume();}}
}

11.创建线程方式三:实现callable()接口

package com.callable;import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;/*** @author ym* @create 2022-01-25 19:31* @description 使用callable方法创建线程  目的是打印100以内所有偶数的和*/
public class CallableDemo {public static void main(String[] args) throws ExecutionException, InterruptedException {ThreadTest threadTest = new ThreadTest();FutureTask<Integer> integerFutureTask = new FutureTask<Integer>(threadTest);Thread thread = new Thread(integerFutureTask);thread.start();Integer integer = integerFutureTask.get();System.out.println(integer);}
}class ThreadTest implements Callable {/*** Computes a result, or throws an exception if unable to do so.** @return computed result* @throws Exception if unable to compute a result*/@Overridepublic Object call() throws Exception {int sum = 0;for (int i = 1; i <= 100; i++) {if (i % 2 == 0) {sum += i;}}return sum;}
}

12.使用线程池

package com.ThreadPool;import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;/*** @author ym* @create 2022-01-25 19:54* @description*/
public class ThreadPool {public static void main(String[] args) {//1.创建线程池ExecutorService executorService = Executors.newFixedThreadPool(10);//4.设置线程池属性ThreadPoolExecutor threadPoolExecutor = (ThreadPoolExecutor) executorService;threadPoolExecutor.setCorePoolSize(15);//2.使用线程池executorService.execute(new Thread1());executorService.submit(new Thread2());//3.关闭线程池executorService.shutdown();}
}class Thread1 implements Runnable {/*** When an object implementing interface <code>Runnable</code> is used* to create a thread, starting the thread causes the object's* <code>run</code> method to be called in that separately executing* thread.* <p>* The general contract of the method <code>run</code> is that it may* take any action whatsoever.** @see Thread#run()*/@Overridepublic void run() {for (int i = 0; i < 10; i++) {System.out.println(Thread.currentThread().getName() + ":" + i);}}
}class Thread2 implements Callable {/*** Computes a result, or throws an exception if unable to do so.** @return computed result* @throws Exception if unable to compute a result*/@Overridepublic Object call() throws Exception {for (int i = 10; i < 20; i++) {System.out.println(Thread.currentThread().getName() + ":" + i);}return null;}
}

java(八) —— 线程安全与线程池问题相关推荐

  1. java(八)-线程安全、volatile关键字、原子性、并发包、死锁、线程池

    Day08[线程状态.volatile关键字.原子性.并发包.死锁.线程池] 今日目标 线程安全 volatile关键字 原子性 并发包 死锁 线程池 教学目标 能够说出volatile关键字的作用 ...

  2. Java基础加强重温_08:线程不安全、线程同步、线程状态、线程状态切换、线程池(Executors类、newFixedThreadPool)、死锁、Lambda表达式、Stream

    摘要 Java基础加强重温_08: 线程安全(线程安全概念.线程不安全案例). 线程同步(同步代码块.同步方法.Lock锁,锁对象). 线程状态(new新建.Runnable可运行.Blocked锁阻 ...

  3. Java多线程知识点整理(线程池)

    2019独角兽企业重金招聘Python工程师标准>>> 1.线程池的使用 线程池一般配合队列一起工作,是线程池限制并发处理任务的数量.然后设置队列的大小,当任务超过队列大小时,通过一 ...

  4. Java面试经典题:线程池的成长之路

    本文转载自公众号: 猿天地 1.背景 相信大家在面试过程中遇到面试官问线程的很多,线程过后就是线程池了.从易到难,都是这么个过程,还有就是确实很多人在工作中接触线程池比较少,最多的也就是创建一个然后往 ...

  5. java常用的几种线程池

    1. 为什么使用线程池 诸如 Web 服务器.数据库服务器.文件服务器或邮件服务器之类的许多服务器应用程序都面向处理来自某些远程来源的大量短小的任务.请求以某种方式到达服务器,这种方式可能是通过网络协 ...

  6. 【Java 并发编程】线程池机制 ( ThreadPoolExecutor 线程池构造参数分析 | 核心线程数 | 最大线程数 | 非核心线程存活时间 | 任务阻塞队列 )

    文章目录 前言 一.ThreadPoolExecutor 构造参数 二.newCachedThreadPool 参数分析 三.newFixedThreadPool 参数分析 四.newSingleTh ...

  7. 【Java 并发编程】线程池机制 ( 测试线程开销 | 启动线程分析 | 用户态 | 内核态 | 用户线程 | 内核线程 | 轻量级进程 )

    文章目录 一.测试线程开销 1.正常测试 2.不创建线程 3.只创建不启动线程 4.只启动不等待执行完成 二.分析测试结果 1.启动线程分析 2.用户线程与内核线程 3.轻量级进程 4.验证 Java ...

  8. Java高并发编程:线程池

    这里首先介绍了java5中的并发的小工具包:java.util.concurrent.atomic,然后介绍了线程池的概念,对使用java5的方式创建不同形式的线程进行了演示,之后介绍了两个 对象:C ...

  9. Java的Executor框架和线程池实现原理

    一,Java的Executor框架 1,Executor接口 public interface Executor {void execute(Runnable command);} Executor接 ...

  10. java线程池_Java多线程并发:线程基本方法+线程池原理+阻塞队列原理技术分享...

    线程基本方法有哪些? 线程相关的基本方法有 wait,notify,notifyAll,sleep,join,yield 等. 线程等待(wait) 调用该方法的线程进入 WAITING 状态,只有等 ...

最新文章

  1. python订单管理系统功能_订单管理系统有哪些功能?
  2. hibernate正向生成数据库表以及配置——Student.hbm.xml
  3. 今天的几经沧桑的飞鸽传书2011
  4. suse linux运行asp,Linux Supervisor的安装与使用入门---SuSE
  5. 【总结】实现点击累加效果的几种方式对比
  6. 文本聚类分析算法_常用的聚类分析算法综述
  7. 使用 Git 生成 SSH Key 并将项目上传到 GitHub
  8. PHP 缓存 内存,php - 一个大型数组变量的APC内存缓存(22MB)
  9. python 运行出现flask运行时提示出错了或者报服务器出错,ValueError: View function did not return a response...
  10. Web 全栈大会:万维网之父的数据主权革命
  11. sla的三个服务等级_联络中心的服务水平标准是什么?
  12. Drupal7导入语言包
  13. 杭州区块链技术与应用联合会简报
  14. Vue.js前端开发实战总结(1)
  15. 抽象类中的非抽象方法调用自己的抽象方法
  16. Sizzle.filter [ 源码分析 ]
  17. 高校党员信息管理系统
  18. 交换机与二层转发原理
  19. [Usaco2008 Mar]The Loathesome Hay Baler麻烦的干草打包机
  20. Incorrect string value: ‘\xE4\xBB\xA3\xE5\x8F\xB7...‘ for column

热门文章

  1. 怎样才可以通过Java培训拿到高薪?-粤嵌教育
  2. Alink 是阿里巴巴基于实时计算引擎 Flink 研发的新
  3. Paper:He参数初始化之《Delving Deep into Rectifiers: Surpassing Human-Level Performance on ImageNet C》的翻译与解读
  4. Unity下落式音游实现——(1)需求分析
  5. 北京是个人吃人的地方
  6. Asp.net MVC 上传大文件(超过50M)的设置
  7. 在ubuntu下通过ssh运行X图形软件(ssh远程访问图形界面)
  8. 硬件均衡负载与软件均衡负载
  9. 华为路由交换机常用命令
  10. LV 旗下公司研发鉴定工具,四秒识别假包包