JAVA学习日记(二十五)多线程

news/2024/12/12 11:14:32/

一、多线程概念

线程:

线程是操作系统能够进行运算调度的最小单位。它被包含在进程中,是进程中的实际运作单位

(应用软件中相互独立,可以同时运行的功能)

进程:

进程是程序的基本执行实体

多线程应用场景:

 

二、并发和并行

并发:

在同一时刻,有多个指令在单个CPU上交替执行

并行:

在同一时刻,有多个指令在多个CPU上同时执行

三、多线程实现方式

继承Thread类的方式:

java">public class Main {public static void main(String[] args) {//多线程 : 继承Thread类实现//定义一个类继承Thread类//重写run方法//创建子类对象    启动线程Method m1=new Method();Method m2=new Method();m1.setName("线程一");m2.setName("线程二");m1.start();m2.start();}
}public class Method extends Thread{@Overridepublic void run() {//线程要执行的代码for(int i=0;i<100;i++){System.out.println(this.getName()+i);}}
}

实现Runnable接口的方式进行实现:

java">public class Main {public static void main(String[] args) {//多线程 : 实现Runnable接口的方式实现//定义一个类实现Runnable接口//重写里面的run方法//创建对象//创建一个Thread类的对象,开启进程Method m1=new Method();Thread thread1=new Thread(m1);Thread thread2=new Thread(m1);thread2.setName("线程二");thread1.setName("线程一");thread1.start();thread2.start();}
}public class Method implements Runnable{public Method() {}@Overridepublic void run() {for (int i=0;i<100;i++){//获取当前线程的对象Thread thread = Thread.currentThread();System.out.println(thread.getName()+i);}}
}

利用Callable接口和Futrue接口方式实现:

java">import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.FutureTask;public class Main {public static void main(String[] args) throws ExecutionException, InterruptedException {//多线程 : 利用Callable接口和Futrue接口方式实现//特点:可以获取多线程运行的结果//定义一个类实现Callable接口//重写里面的call方法 (该方法是有返回值的:返回值表示多线程运行的结果)//创建该类对象  创建FutureTask的对象 (作用是管理多线程运行的结果)//创建一个Thread类的对象,开启进程 (表示线程)Method m1=new Method();FutureTask<Integer> ft=new FutureTask<>(m1);   //(作用是管理多线程运行的结果)Thread thread1=new Thread(ft);thread1.start();//获取多线程运行的结果System.out.println(ft.get()); //45}
}import java.util.concurrent.Callable;public class Method implements Callable<Integer> {//泛型<>  根据返回值(线程运行结果)的类型设定public Method() {}@Overridepublic Integer call() throws Exception {int sum=0;for(int i=0;i<10;i++){sum+=i;}return sum;}
}

对比:

四、Thread常见成员方法 

 前四种:

java">import java.util.concurrent.ExecutionException;public class Main {public static void main(String[] args) throws ExecutionException, InterruptedException {//多线程成员方法//为线程设置名字 方法一:使用setName方法 方法二:子类继承Thread中的构造方法 在构造时直接设置//SetName细节: 线程如果没有设置名字,则会采用默认名字 Thread-X  X为序号 从0开始//获取当前线程对象 currentThread()//细节:当JVM虚拟机启动时,会自动启动多条线程//     其中有一条叫做main线程,作用就是去调用main方法并执行里面的代码//sleep(long time)方法  让线程休眠指定的时间//哪条线程执行到这个方法,该线程就会在这里停顿指定的时间//参数表示休眠的时间,单位是毫秒//当休眠时间结束后会醒来,继续执行下面的代码Mythread mt1=new Mythread();Mythread mt2=new Mythread("哈哈");System.out.println(mt1.getName()); //Thread-1System.out.println(mt2.getName()); //哈哈Thread thread = Thread.currentThread();System.out.println(thread.getName()); //mainMythread mythread=new Mythread();mythread.run();}
}public class Mythread extends Thread{@Overridepublic void run() {for(int i=0;i<100;i++){try {//线程休眠 1秒 Thread.sleep(1000);} catch (InterruptedException e) {throw new RuntimeException(e);}System.out.println(this.getName() + i);};}public Mythread() {}public Mythread(String name) {super(name);}
}

设置获取线程优先级:

java">import java.util.concurrent.ExecutionException;public class Main {public static void main(String[] args) throws ExecutionException, InterruptedException {Method m=new Method();Thread thread1=new Thread(m,"飞机");Thread thread2=new Thread(m,"大炮");//获取优先级 : 默认值为5System.out.println(thread1.getPriority()); //5//设置线程优先级//优先级≠一定先完成   只是代表概率thread1.setPriority(8);thread2.setPriority(1);thread1.start();thread2.start();}
}public class Method implements Runnable {//泛型<>  根据返回值(线程运行结果)的类型设定public Method() {}@Overridepublic void run() {String name=Thread.currentThread().getName();for(int i=0;i<100;i++){System.out.println(name+i);}}
}

设置守护线程:

java">import java.util.concurrent.ExecutionException;public class Main {public static void main(String[] args) throws ExecutionException, InterruptedException {//设置守护线程  final void setDaemon(boolean on)  设置为守护线程//细节:  当其他的非守护线程执行完毕后,守护线程会陆续结束//       当女神线程执行完毕后,舔狗线程会陆续结束Method m=new Method();Thread thread1=new Thread(m,"女神");Thread thread2=new Thread(m,"舔狗");//设置舔狗为守护进程thread2.setDaemon(true);//女神进程一旦结束,舔狗进程也会慢慢停止thread1.start();thread2.start();}
}public class Method implements Runnable {//泛型<>  根据返回值(线程运行结果)的类型设定public Method() {}@Overridepublic void run() {String name=Thread.currentThread().getName();for(int i=0;i<100;i++){System.out.println(name+i);}}
}

出让线程/礼让线程+ 插入线程/插队线程:

java">import java.util.concurrent.ExecutionException;public class Main {public static void main(String[] args) throws ExecutionException, InterruptedException {//出让线程/礼让线程Mythread m1=new Mythread("fff");Mythread m2=new Mythread("ddd");m1.start();m2.start();//表示把m1 m2这个线程,插入到当前线程之前//当前线程:main线程m1.join();m2.join();for(int i=0;i<10;i++){System.out.println("main线程"+i);}}
}public class Mythread extends Thread{@Overridepublic void run() {for(int i=0;i<100;i++){System.out.println(this.getName() + i);//出让当前CPU使用权  (重新和其他线程抢夺CPU使用权)Thread.yield();};}public Mythread() {}public Mythread(String name) {super(name);}
}

五、线程的生命周期

 六、线程的安全问题(同步代码块+同步方法)

 

java">import java.util.concurrent.ExecutionException;public class Main {public static void main(String[] args) throws ExecutionException, InterruptedException {Method m=new Method();Thread thread1=new Thread(m,"窗口一:");Thread thread2=new Thread(m,"窗口二:");Thread thread3=new Thread(m,"窗口三:");thread1.start();thread2.start();thread3.start();}
}public class Method implements Runnable {//泛型<>  根据返回值(线程运行结果)的类型设定private  static int ticket=0;//锁对象一定要是唯一的 (使用static修饰)private static Object obj=new Object();public Method() {}@Overridepublic void run() {String name=Thread.currentThread().getName();//同步代码块synchronized (obj){while (true) {if (ticket < 100) {try {Thread.sleep(100);} catch (InterruptedException e) {throw new RuntimeException(e);}ticket++;System.out.println(name + ticket);} elsebreak;}}}
}public class Method implements Runnable {//泛型<>  根据返回值(线程运行结果)的类型设定private  static int ticket=0;//锁对象一定要是唯一的 (使用static修饰)private static Object obj=new Object();public Method() {}@Overridepublic void run() {//同步方法extracted();}private synchronized static void extracted() {synchronized (obj){String name=Thread.currentThread().getName();while (true) {if (ticket < 100) {try {Thread.sleep(100);} catch (InterruptedException e) {throw new RuntimeException(e);}ticket++;System.out.println(name + ticket);} elsebreak;}}}}

七、Lock锁

java">import java.util.concurrent.ExecutionException;public class Main {public static void main(String[] args) throws ExecutionException, InterruptedException {Method m=new Method();Thread thread1=new Thread(m,"窗口一:");Thread thread2=new Thread(m,"窗口二:");Thread thread3=new Thread(m,"窗口三:");thread1.start();thread2.start();thread3.start();}
}import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;public class Method implements Runnable {//泛型<>  根据返回值(线程运行结果)的类型设定private  static int ticket=0;//锁对象一定要是唯一的 (使用static修饰)//Lock是一个接口,需要用其实现类创建对象private static Lock lock=new ReentrantLock();public Method() {}@Overridepublic void run() {//同步代码块String name=Thread.currentThread().getName();while (true) {lock.lock();try {if (ticket < 100) {Thread.sleep(100);ticket++;System.out.println(name + ticket);} else {break;}} catch (InterruptedException e) {throw new RuntimeException(e);} finally {lock.unlock();}}}
}

八、等待唤醒机制

 

 

java">import java.util.concurrent.ExecutionException;public class Main {public static void main(String[] args) throws ExecutionException, InterruptedException {Cook c=new Cook();Foodeat f=new Foodeat();c.setName("厨师");f.setName("吃货");c.start();f.start();}
}public class Foodeat extends Thread{@Overridepublic void run() {/*1、循环2、同步代码块3、判断共享数据是否到了末尾(到了末尾)4、判断共享数据是否到了末尾(没有到达末尾,执行核心逻辑)*/while(true){synchronized (Table.lock){if(Table.count==0){//到了末尾break;}else{//1、判断是否有食物//2、如果有则开吃  修改食物总数 唤醒厨师继续做//3、如果没有则等待//4、修改桌子状态if(Table.foodflag==0){//桌子上没有食物 进行等待try {Table.lock.wait();  //让当前线程和锁进行绑定} catch (InterruptedException e) {throw new RuntimeException(e);}}else{//桌子上有食物  开吃Table.count--;System.out.println("吃货正在吃面,还能再吃"+Table.count+"碗面");Table.foodflag=0;Table.lock.notifyAll(); //唤醒厨师去做菜}}}}}}public class Cook extends Thread {@Overridepublic void run() {while(true){synchronized (Table.lock){//判断共享数据是否到达末尾if(Table.count==0){//到达末尾:已经吃不下了break;}else{//没有,对是否有食物进行判断if(Table.foodflag==0){//没有食物System.out.println("厨师已经做了一碗面");Table.foodflag=1;//唤醒吃货开吃Table.lock.notifyAll();}else{//有食物try {Table.lock.wait();  //等待 将该线程与lock锁绑定,方便后续唤醒} catch (InterruptedException e) {throw new RuntimeException(e);}}}}}}
}import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;public class Table {public static int count=10;//foodflag=1: 桌子上有食物  foodflag=0 :桌子上没有食物public static int foodflag=0;//锁对象public static Lock lock=new ReentrantLock();
}

九、阻塞队列实现等待唤醒机制

 

java">import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ExecutionException;public class Main {public static void main(String[] args) throws ExecutionException, InterruptedException {//利用阻塞队列完成等待唤醒机制//生产者和消费者必须使用同一个队列//1、创建阻塞队列对象ArrayBlockingQueue<String> queue=new ArrayBlockingQueue<>(1); //指定1为队列上限Cook c=new Cook(queue);Foodeat f=new Foodeat(queue);c.setName("厨师");f.setName("吃货");c.start();f.start();}
}import java.util.concurrent.ArrayBlockingQueue;public class Foodeat extends Thread{ArrayBlockingQueue<String> queue;public Foodeat(ArrayBlockingQueue<String> queue){this.queue=queue;}@Overridepublic void run() {while(true){try {String food=queue.take();System.out.println("吃货吃了一碗"+food);} catch (InterruptedException e) {throw new RuntimeException(e);}}}}import java.util.concurrent.ArrayBlockingQueue;public class Cook extends Thread {ArrayBlockingQueue<String> queue;public Cook(ArrayBlockingQueue<String> queue){this.queue=queue;}@Overridepublic void run() {while(true){try {queue.put("面条");System.out.println("厨师做了一碗面");} catch (InterruptedException e) {throw new RuntimeException(e);}}}
}

十、多线程的六种状态

 


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

相关文章

Connection对象,Statement对象和ResultSet对象的依赖关系 JDBC

在JDBC&#xff08;Java Database Connectivity&#xff09;中&#xff0c;Connection、Statement和ResultSet是三个主要的接口&#xff0c;用于与数据库进行交互。当Connection被关闭时&#xff0c;与之关联的Statement和ResultSet对象也会被关闭&#xff0c;这是因为它们之间…

梳理你的思路(从OOP到架构设计)_基本OOP知识03

目录 1、<基类/子类 >结构的接口(卡榫函数) 1&#xff09;卡榫(Hook) 2&#xff09;卡榫函数的Java实现 2、IoC机制与基於 Default 軟硬整合觀點 函数 1&#xff09;卡榫函数实现IoC机制 2&#xff09;默认(Default)行为 1、<基类/子类 >结构的接口(卡榫函数…

容器部署Prometheus+Grafana

一、Grafana介绍 Zabbix 和 Grafana 是两种流行的监控工具,它们在功能和用途上有所不同: Zabbix: Zabbix 是一个开源的监控解决方案,主要用于监控网络服务和应用程序。它包括了自己的数据存储解决方案,可以直接从监控的设备收集数据。Zabbix 提供了广泛的监控功能,包括但…

【离线环境迁移】使用Conda打包和还原Python环境指南

本文介绍了一种利用Conda工具快速打包和迁移Python环境的方法。 通过简单的步骤&#xff0c;轻松实现离线服务器的环境配置&#xff0c;解决网络限制问题。 1.创建环境并安装相关依赖 conda create -n myenv python3.x conda activate myenv conda install <package_list&g…

Linux絮絮叨(六) 文件与目录管理

Linux 的目录结构为树状结构&#xff0c;最顶级目录为根目录 / 绝对路径与相对路径 绝对路径&#xff1a;以 / 为起点的路径&#xff0c;例如 /usr/share/doc。相对路径&#xff1a;以当前路径为起点的路径&#xff0c;例如 cd ../man。 常用命令 1. ls (列出目录内容) 功能…

51c深度学习~合集9

我自己的原文哦~ https://blog.51cto.com/whaosoft/12750420 #傅里叶特征 (Fourier Feature&#xff09;与核回归 位置编码背后的理论解释 本文探讨了位置编码背后的理论基础&#xff0c;特别是傅里叶特征&#xff08;Fourier Feature&#xff09;与核回归&#xff08;Kern…

D 咖智能饮品机器人,门店引流新宠

在竞争激烈的商业环境中&#xff0c;门店客流量的竞争已进入白热化阶段。如何让路过门店的客户停下脚步&#xff0c;成为众多商家亟待解决的难题。传统的纸质海报往往难以吸引客户的注意力&#xff0c;而店员拉客的方式效率又相对低下&#xff0c;在这种情况下&#xff0c;D 咖…

使用Python和PyQt5实现Modbus TCP协议下的量程切换功能

使用Python和PyQt5实现Modbus TCP协议下的量程切换功能 在工业自动化系统中&#xff0c;设备的量程切换是一个常见的需求。本文将介绍如何使用Python和PyQt5开发一个图形用户界面&#xff08;GUI&#xff09;应用程序&#xff0c;以通过Modbus TCP协议向设备发送特定的指令&am…