JAVA关于多线程的学习

news/2025/2/7 7:32:11/

1.创建线程的方法(这里不考虑继承Thread类)

通过实现Runnable接口的方式实现

public class MyRunnable implements Runnable{@Overridepublic void run() {for (int i = 0; i < 5; i++) {System.out.println(Thread.currentThread().getName()+"执行了....");}}
}public class Test01 {public static void main(String[] args) {MyRunnable myRunnable = new MyRunnable();Thread thread = new Thread(myRunnable);// 也可以直接写匿名类thread.start();for (int i = 0; i < 5; i++) {System.out.println(Thread.currentThread().getName()+"执行了....");}}
}

2.同步代码块

同一个时间,只有一个线程可以运行,锁住
注意,必须是同一把锁,当然,由于基本数据类型的特殊性,有些基本数据类型也是可以锁住的,比如 Integer = (0-127) 之内是可以充当锁的,当然,锁只能锁住使用他的线程。

1.格式

synchronized(任意对象){
可能出现线程安全的代码
}

2.代码

public class Test {public static void main(String[] args) {Ticket ticket = new Ticket();Thread t1 = new Thread(ticket, "赵四");Thread t2 = new Thread(ticket, "广坤");Thread t3 = new Thread(ticket, "刘能");//开启线程t1.start();t2.start();t3.start();}
}
public class Ticket implements Runnable{int ticket = 100;//创建一个对象充当锁对象Object obj = new Object();@Overridepublic void run() {while(true){try {Thread.sleep(100L);} catch (InterruptedException e) {e.printStackTrace();}synchronized (obj){if (ticket>0){System.out.println(Thread.currentThread().getName()+"买了第"+ticket+"张票");ticket--;}}}}
}

3.同步方法

1.介绍

关键字是synchrosnized 锁 this
所以,runnable的实现类要是同一个对象
或者使用static方法 这时候锁就是 类.class

2.代码块

public class Ticket implements Runnable {int ticket = 100;@Overridepublic void run() {while (true) {try {Thread.sleep(100L);} catch (InterruptedException e) {e.printStackTrace();}method();}}/*  public synchronized void method() {if (ticket > 0) {System.out.println(Thread.currentThread().getName() + "买了第" + ticket + "张票");ticket--;}}*/public void method() {synchronized (this){if (ticket > 0) {System.out.println(Thread.currentThread().getName() + "买了第" + ticket + "张票");ticket--;}}}
}

4.关于对一个类的不同业务的思考

如果对一个类的不同业务处理,应该怎么处理呢?
线程如果对一个类进行操作,或者根据一个类的数据进行相应的方法调用?
首先第一点,必须要拿到这个类的数据,所以,必须要拿到这个类的对象,或者是这个类的子类。

  1. 将业务方法写在类中,然后通过类的对象进行调用
  2. 将业务方法写在线程类中,线程类中存一个类的对象。

1.包子铺代码

做一个卖一个

//包子铺代码 操作对象
public class BaoZiPu {//定义一个count证明生产包子,消费包子private int count;//定义一个flag,证明有没有包子private boolean flag;public BaoZiPu() {}public BaoZiPu(int count, boolean flag) {this.count = count;this.flag = flag;}//专门给消费线程服务public void getCount() {System.out.println("消费了第"+count+"个包子...........");}//专门给生产线程服务public void setCount() {count++;System.out.println("生产了第"+count+"个包子....");}public boolean isFlag() {return flag;}public void setFlag(boolean flag) {this.flag = flag;}}
//  实现类 
public class Consumer implements Runnable{private BaoZiPu baoZiPu;public Consumer(BaoZiPu baoZiPu){this.baoZiPu = baoZiPu;}@Overridepublic void run() {while(true){try {Thread.sleep(100L);} catch (InterruptedException e) {e.printStackTrace();}synchronized (baoZiPu){//如果flag等于false.证明没有包子,消费线程等待if (baoZiPu.isFlag() == false){try {baoZiPu.wait();} catch (InterruptedException e) {e.printStackTrace();}}//如果flag为true,证明有包子,消费包子,然后唤醒生活线程baoZiPu.getCount();//改变flag状态为false,证明没有包子了baoZiPu.setFlag(false);//唤醒生产线程baoZiPu.notify();}}}
}
public class Product implements Runnable{private BaoZiPu baoZiPu;public Product(BaoZiPu baoZiPu){this.baoZiPu = baoZiPu;}@Overridepublic void run() {while(true){try {Thread.sleep(100L);} catch (InterruptedException e) {e.printStackTrace();}synchronized (baoZiPu){//如果flag等于true.证明有包子,生产线程等待if (baoZiPu.isFlag() == true){try {baoZiPu.wait();} catch (InterruptedException e) {e.printStackTrace();}}//如果flag为false,证明没有包子,生产包子,然后唤醒消费线程baoZiPu.setCount();//改变flag状态为true,证明有包子了baoZiPu.setFlag(true);//唤醒消费线程baoZiPu.notify();}}}
}
 public static void main(String[] args) throws Exception{BaoZiPu baoZiPu = new BaoZiPu();Thread t1 = new Thread(new Product(baoZiPu));Thread t2 = new Thread(new Consumer(baoZiPu));t1.start();t2.start();}

问题:
1.为什么wait不能放在最后执行

while(true){try {Thread.sleep(100L);} catch (InterruptedException e) {e.printStackTrace();}synchronized (baoZiPu){//如果flag等于true.证明有包子,生产线程等待if (baoZiPu.isFlag() == true){//如果flag为false,证明没有包子,生产包子,然后唤醒消费线程baoZiPu.setCount();//改变flag状态为true,证明有包子了baoZiPu.setFlag(true);//唤醒消费线程baoZiPu.notify();try {baoZiPu.wait();} catch (InterruptedException e) {e.printStackTrace();}}}}

因为notify是将线程唤醒,线程是跟着wait继续走的,这时候直接循环,但是,如果拿到锁却拿不到条件,直接卡死在这里了
在这里插入图片描述

2.多生产多消费的包子铺

notifyAll 但是这样还是消耗资源比较严重,因为有可能出现多次重复拿到锁但是无法运行放弃锁,并且有些拿不到锁的也唤醒了.

public class BaoZiPu {//定义一个count证明生产包子,消费包子private int count;//定义一个flag,证明有没有包子private boolean flag;public BaoZiPu() {}public BaoZiPu(int count, boolean flag) {this.count = count;this.flag = flag;}//专门给消费线程服务public synchronized void getCount() {//如果flag等于false.证明没有包子,消费线程等待while (flag == false) {try {this.wait();} catch (InterruptedException e) {e.printStackTrace();}}//如果flag为true,证明有包子,消费包子,然后唤醒生活线程System.out.println("消费了第" + count + "个包子...........");//改变flag状态为false,证明没有包子了flag = false;//唤醒生产线程this.notifyAll();}//专门给生产线程服务public synchronized void setCount() {//如果flag等于true.证明有包子,生产线程等待while (flag == true) {try {this.wait();} catch (InterruptedException e) {e.printStackTrace();}}//如果flag为false,证明没有包子,生产包子,然后唤醒消费线程count++;System.out.println("生产了第" + count + "个包子....");//改变flag状态为true,证明有包子了flag = true;//唤醒消费线程this.notifyAll();}public boolean isFlag() {return flag;}public void setFlag(boolean flag) {this.flag = flag;}
}
public class Consumer implements Runnable{private BaoZiPu baoZiPu;public Consumer(BaoZiPu baoZiPu){this.baoZiPu = baoZiPu;}@Overridepublic void run() {while(true){try {Thread.sleep(100L);} catch (InterruptedException e) {e.printStackTrace();}baoZiPu.getCount();}}
}
public class Product implements Runnable{private BaoZiPu baoZiPu;public Product(BaoZiPu baoZiPu){this.baoZiPu = baoZiPu;}@Overridepublic void run() {while(true){try {Thread.sleep(100L);} catch (InterruptedException e) {e.printStackTrace();}baoZiPu.setCount();}}
}
public class Test01 {public static void main(String[] args) {//创建包子铺对象BaoZiPu baoZiPu = new BaoZiPu();Product product = new Product(baoZiPu);Consumer consumer = new Consumer(baoZiPu);//两个生产线程new Thread(product).start();new Thread(product).start();//两个消费线程new Thread(consumer).start();new Thread(consumer).start();}
}

5.Lock

1. 介绍

   Lock lock = new ReentrantLock();lock.lock();// 加锁lock.unlock(); // 解锁

6.condition阻塞队列

 void await() ->线程等待  // 让当前线程等等void signal()->线程唤醒 // 从队列中唤醒一个等待线程Condition condition = lock.newCondition();

可以分业务唤醒队列,一个队列一个业务

1.包子例题

public class BaoZiPu {//定义一个count证明生产包子,消费包子private int count;//定义一个flag,证明有没有包子private boolean flag;//创建Lock对象Lock lock = new ReentrantLock();//为生产者创建Condition对象Condition productCondition = lock.newCondition();//为消费者创建Condition对象Condition consumerCondition = lock.newCondition();public BaoZiPu() {}public BaoZiPu(int count, boolean flag) {this.count = count;this.flag = flag;}//专门给消费线程服务public  void getCount() {//获取锁lock.lock();//如果flag等于false.证明没有包子,消费线程等待while (flag == false) {try {//消费线程等待consumerCondition.await();} catch (InterruptedException e) {e.printStackTrace();}}//如果flag为true,证明有包子,消费包子,然后唤醒生活线程System.out.println("消费了第" + count + "个包子...........");//改变flag状态为false,证明没有包子了flag = false;//唤醒生产线程productCondition.signal();//释放锁lock.unlock();}//专门给生产线程服务public  void setCount() {//获取锁lock.lock();//如果flag等于true.证明有包子,生产线程等待while (flag == true) {try {//生产线程等待productCondition.await();} catch (InterruptedException e) {e.printStackTrace();}}//如果flag为false,证明没有包子,生产包子,然后唤醒消费线程count++;System.out.println("生产了第" + count + "个包子....");//改变flag状态为true,证明有包子了flag = true;//唤醒消费线程consumerCondition.signal();//释放锁lock.unlock();}public boolean isFlag() {return flag;}public void setFlag(boolean flag) {this.flag = flag;}
}
public class Consumer implements Runnable{private BaoZiPu baoZiPu;public Consumer(BaoZiPu baoZiPu){this.baoZiPu = baoZiPu;}@Overridepublic void run() {while(true){try {Thread.sleep(100L);} catch (InterruptedException e) {e.printStackTrace();}baoZiPu.getCount();}}
}
public class Product implements Runnable{private BaoZiPu baoZiPu;public Product(BaoZiPu baoZiPu){this.baoZiPu = baoZiPu;}@Overridepublic void run() {while(true){try {Thread.sleep(100L);} catch (InterruptedException e) {e.printStackTrace();}baoZiPu.setCount();}}
}
public class Test01 {public static void main(String[] args) {//创建包子铺对象BaoZiPu baoZiPu = new BaoZiPu();Product product = new Product(baoZiPu);Consumer consumer = new Consumer(baoZiPu);//两个生产线程new Thread(product).start();new Thread(product).start();//两个消费线程new Thread(consumer).start();new Thread(consumer).start();}
}

http://www.ppmy.cn/news/750869.html

相关文章

Elasticsearch:注册域处理器 - registered domain processor

从完全限定域名 (fully qualified domain name - FQDN) 中提取注册域&#xff08;也称为有效顶级域或 eTLD&#xff09;、子域和顶级域。 使用 Mozilla 公共后缀列表中定义的注册域。 它有如下的选项&#xff1a; 名称必须默认描述fieldyes包含源 FQDN 的字段。target_fieldn…

CPU套路篇:cpu性能优化的几个思路???

性能优化方法论&#xff1a; 找到系统瓶颈后&#xff0c; 怎么判断优化是否有效&#xff0c;并且能提升多少性能&#xff1f;&#xff1f;如果有多个性能问题&#xff0c;应该先优化哪一个&#xff1f;&#xff1f;提升性能的方法并不是唯一的&#xff0c;当有多种方法可以选…

程序开发性能调优之如何降低CPU使用率。

单核的CUP就100%&#xff01;双核的就60%&#xff01;这谁受的了。咋调都不行。我把所有的效果都关了&#xff0c;还不行&#xff01;连声音都关了&#xff0c;就剩个窗口模式了&#xff01;他照样100%&#xff01;咋整啊&#xff1f; 改用静态的方式的确是能够大大降低数据库…

cpu 性能优化思路

cpu 性能优化思路 文章目录 cpu 性能优化思路前言一、性能优化方法论cpu性能优化工具性能优化是否有效多个性能问题同时存在&#xff0c;要怎么选择&#xff1f;有多种优化方法时&#xff0c;要如何选择? 二、CPU 优化应用程序优化系统优化 总结 前言 虽然 CPU 的性能指标很多…

性能优化(内存)

个人在极客时间、工作经验、技术博客的总结。 背景 比较windows和linux的内存管理的区别 概念 地址空间 每一个32位进程都有4G的地址&#xff0c;其中2G内核空间&#xff0c;2G用户空间&#xff08;linux 是1G内核&#xff0c;3G用户&#xff09;。 这个地址空间实际是虚…

Linux性能优化-CPU性能优化思路

目录 CPU性能指标 性能工具 如何迅速的分析CPU性能瓶颈 性能优化方法论 CPU优化 参考 CPU性能指标 CPU使用率 1.CPU使用率描述了非空闲时间占总CPU时间的百分比&#xff0c;根据CPU上运行任务的不同&#xff0c;又被分为 用户CPU&#xff0c;系统CPU&#xff0c;等待…

Linux性能优化之CPU、内存、IO优化

Linux 的性能进行监测&#xff0c;以下是 VPSee 常用的工具&#xff1a;工具 简单介绍top 查看进程活动状态以及一些系统状况vmstat 查看系统状态、硬件和系统信息等iostat 查看CPU 负载&#xff0c;硬盘状况sar 综合工具&#xff0c;查看系统状况mpstat 查看…

应用程序性能瓶颈中的CPU缓存优化

1.前言 在应用程序中会有大量的对变量的操作&#xff0c;在一般情况下不会导致问题&#xff0c;但在多线程操作共享变量时&#xff0c;不当的操作会产生大量的冗余操作&#xff0c;造成性能的浪费。这篇文章主要从编码方式与逻辑策略对变量从CPU寄存器&#xff0c;CPU缓存&…