http://www.ibm.com/developerworks/library/j-jtp0730/index.html
学习编程的目的:解决问题/开发用户需要的功能
多线程可以解决什么问题?
将不同的子任务交给不同的线程去执行,提高系统响应速度(比单一线程执行所有任务更快)
从最简单的开始,如何创建线程!
run() : 封装线程要运行的任务,所以将线程要运行的代码封装到run()中即可!
方式一:创建一个类直接继承Thread类,并覆盖run()
方式二:创建一个类实现Runnable接口,实现run(),再将此类的实例传入Thread构造方法中
开启线程:
new Thread().start();
new Thread(MyTask).start(); [ MyTask implements Runnable ]
线程的几种状态切换
两种使用线程的方式:
package thread; /** * 多线程使用方式一: * 通过继承Thread类让子类成为线程类 * 再通过该线程类开启线程执行任务 * */ public class ThreadDemo_A extends Thread { public ThreadDemo_A(String threadName) { //将线程名称传入父类构造方法,设置父线程的name,子类再将此name继承下来 super(threadName); } @Override public void run() {//run()封装线程需要执行的任务 for(int i=0;i<100;i++) { //获取当前线程名称 System.out.println(Thread.currentThread().getName()); } } public static void main(String[] args) { //主线程 System.out.println("main() start"); ThreadDemo_A a = new ThreadDemo_A("work_11111"); a.start();//开启另外1个线程 new ThreadDemo_A("work_22222").start();//再开启1个线程 System.out.println("main() end"); } }
推荐的方式--->通过Runnable封装线程任务
package thread; /** * 多线程使用方式二: * 通过实现 Runnable 接口,在run()中定义需要由线程执行的任务 * 然后将子类实例传递到Thread构造函数中,让Thread类去开启线程执行子类中的run() * */ public class ThreadDemo_B implements Runnable { private String address; private String content; public ThreadDemo_B() {} public ThreadDemo_B(String address, String content) { this.address = address; this.content = content; } @Override public void run() { sendEmail();//线程任务:发送邮件 } private void sendEmail() { for(int i=0;i<100;i++) System.out.println(Thread.currentThread().getName()+"------->>>>"+"Send email to " + address +", content=" + content); } public static void main(String[] args) { ThreadDemo_B task1 = new ThreadDemo_B("1@1.com", "1111111"); ThreadDemo_B task2 = new ThreadDemo_B("2@2.com", "2222222"); new Thread(task1,"线程111111").start(); new Thread(task2,"线程222222").start(); } }
==========================================================================
单个线程操作资源不存在同步、异步。
同步:WC,进入后上锁,出来后打开锁。
通过同步(加锁)来解决多线程操作共享资源时的安全问题!
同步的弊端:效率低(操作共享资源之前,线程都需要判断锁,如果锁没有释放,是进入不了的,会一直等待锁的释放)。
什么时候需要使用同步?
多个线程操作共享资源
且必须使用同一个锁,才能实现多线程同步访问的效果!
不同情况下的同一 个锁:
同步代码块使用的锁:堆内存中的任何相同对象(内存地址相同,即同一个对象)。
Runnable中定义一个成员对象,如 Object locker = new Object();
synchronized(locker)使用的就是同一个锁;
同步函数使用的锁:this
静态同步函数使用的锁:该方法所属类的字节码对象 Ticket.class
Java提供的处理同步问题的办法:
同步代码块
public void doIt() { doSomething.... //操作共享资源的代码,使用同步代码库对其封装 synchronized (Task.class) { ... } doOtherthing... }
同步函数
//使用同步函数封装那些涉及共享资源操作的代码 public synchronized void doIt() { //操作共享资源的代码 code... }
由于同步中使用的锁可以是任何对象,所以wait(),notify(),notifyAll()被定义在Object中!
wait(),notify(),notifyAll()是绑定在同一个锁上相互进行通信的!
wait() : 某种不满足操作的情况下,线程让自己进入等待状态!locker.wait()
notify(): 当线程自己进入等待状态后,调用notify()唤醒线程池中的一个线程,只唤醒一个(可能唤醒的是本方线程,造成死锁)。locker.notify()
notifyAll() : 唤醒线程池中所有等待的线程,可以避免死锁的发生。locker.notifyAll()
package thread; /** * 简单的2个线程间交替执行示例 * 通过synchronized保证对资源的“原子操作”不被打断 * 通过线程通信实现切换运行 */ public class TwoThreadsCommunication { public static void main(String[] args) { new TwoThreadsCommunication().justDoIt(); } public void justDoIt() { final ResourceHandler r = new ResourceHandler(); new Thread(new Runnable() { public void run() { for(int i=0;i<100;i++) r.produce(); } }, "线程A").start(); new Thread(new Runnable() { public void run() { for(int i=0;i<100;i++) r.consume(); } }, "线程B").start(); } /** * 资源类 * * 将多线程操作的代码单独封装起来,然后在run()中通过对象来调用 * 将同步放到资源上,而不是在run()中进行控制,实现与具体线程的解耦 * 互斥不要放到线程上进行,而应该放到对资源类操作的方法中!!! */ class ResourceHandler { //状态变量在资源内部进行操作 private boolean full; //生产线程操作共享资源的方法 public synchronized void produce() { //notice: 这里用while,不要用if。可防止死锁! while(full) { try { this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } for(int i=1;i<=10;i++) { System.out.println(Thread.currentThread().getName()+" run***" + i); } full = true; this.notify(); } //消费线程操作共享资源的方法 public synchronized void consume() { //notice: 这里用while,不要用if。可防止死锁! while(!full) { try { this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } for(int j=1;j<=10;j++) { System.out.println(Thread.currentThread().getName()+" run******" + j); } full = false; this.notify(); } } }
多线程间共享资源的方式:
package thread; /** * 多线程共享资源的方式一: * * 操作共享资源的run()放到内部类中,然后操作外部类中定义的资源 * * 1个线程负责加,1个线程负责减 */ public class ShareDataStyle1 { private int sharedData = 100; public synchronized void add() { sharedData++; System.out.println(Thread.currentThread().getName()+" add:" + sharedData); } public synchronized void minus() { sharedData--; System.out.println(Thread.currentThread().getName()+" minus:" + sharedData); } //内部类访问外部类的共享资源 class Add implements Runnable { public void run() { while(true) add(); } } //内部类访问外部类的共享资源 class Minus implements Runnable { public void run() { while(true) minus(); } } public static void main(String[] args) { ShareDataStyle1 sharedDate = new ShareDataStyle1(); new Thread(sharedDate.new Add()).start(); new Thread(sharedDate.new Minus()).start(); } }
package thread; /** * 多线程共享资源的方式二: * * 将共享资源传递到不同的Runnable对象中 * * 1个线程负责加,1个线程负责减 */ public class ShareDataStyle2 { public static void main(String[] args) { SharedData data = new SharedData(); new Thread(new Add(data)).start(); new Thread(new Minus(data)).start(); } } class SharedData { private int sharedData = 100; public synchronized void add() { sharedData++; System.out.println(Thread.currentThread().getName()+" add:" + sharedData); } public synchronized void minus() { sharedData--; System.out.println(Thread.currentThread().getName()+" minus:" + sharedData); } } class Add implements Runnable { SharedData sharedData; public Add(SharedData sharedData) { this.sharedData = sharedData; } public void run() { while(true) sharedData.add(); } } class Minus implements Runnable { SharedData sharedData; public Minus(SharedData sharedData) { this.sharedData = sharedData; } public void run() { while(true) sharedData.minus(); } }
异步:游泳池,往里跳,往外出,互不干扰,这就是异步。
同步:解决多个线程操作共享资源发生安全隐患!
A线程在执行某个代码片段,B线程在A线程释放锁之前将被阻塞(同一个监视器下)。
而异步呢:多个线程以并行工作的方式协同完成整体任务,目的是更快的完成当前任务!
一个耗时较长的任务,如果可以被分割为几个小的部分,而且这几个部分没有前后依赖关系,则可以并行的执行(充分利用多CPU的能力),提高处理速度。
=======================================================================
几个容易混淆的概念
wait : 当前线程将释放CPU,释放锁
sleep : 当前线程将释放CPU,不释放锁
InterruptedException:
线程当前所处状态被清除时,如,本来线程A正在sleep(5000),当到2000ms时,突然其sleep状态被清除了,此时,线程A将继续进行执行。只是,这种情况发生之后,JVM会抛出InterruptedException 到该线程上,告诉你线程A非正常醒了,是否需要处理这种非正常的醒就看程序员如果处理该异常了!
需要理解的是:发生InterruptedException不代表当前线程结束了!
一般情况下,这种非正常状态改变发生后,直接让方法return即可!
调用线程t的interrupt()便可以让t线程发生InterruptedException,然后在catch块中改变程序执行控制标记,或者return都行,具体怎么弄就看情况了!
守护线程:setDeamon(boolean b)
当所有线程都是守护线程时,JVM就会自动退出。
如,设置一个守护线程专门管理系统的缓存:
Thread cacheThread = new Thread(new CacheManager());
cacheThread.setDeamon(true); //必须在开启线程之前进行设置
cacheThread.start();
线程结合点:join()
切入一个新的线程到当前环境,只有切入的线程执行完毕后,当前线程才会继续执行
Thread subThread = new SubThread();
subThread.join();//直到subThread执行完毕,当前线程才继续往下执行
线程优先级
Thread t1 = new Thread();
t1.setPriority(Thread.MAX_PRIORITY);//最高优先级:10
Thread t2 = new Thread();
t2.setPriority(Thread.MIN_PRIORITY);//最低优先级:1
Thread t3 = new Thread();
t3.setPriority(Thread.NORM_PRIORITY);//默认优先级:5
线程组ThreadGroup
将若干功能相似的线程放到一个组中,便于统一管理。如统一设置优先级等
相关推荐
docker imagedocker-compose
COMSOL 21700电池针刺热失控实验与结果分析,comsol 21700针刺热失控 ,comsol; 21700针; 刺热失控,COMSOL研究:21700电池针刺热失控现象解析
1.版本:matlab2014/2019a/2024a 2.附赠案例数据可直接运行matlab程序。 3.代码特点:参数化编程、参数可方便更改、代码编程思路清晰、注释明细。 4.适用对象:计算机,电子信息工程、数学等专业的大学生课程设计、期末大作业和毕业设计。
1、文件内容:perl-File-ShareDir-1.03-8.el7.rpm以及相关依赖 2、文件形式:tar.gz压缩包 3、安装指令: #Step1、解压 tar -zxvf /mnt/data/output/perl-File-ShareDir-1.03-8.el7.tar.gz #Step2、进入解压后的目录,执行安装 sudo rpm -ivh *.rpm 4、安装指导:私信博主,全程指导安装
免费JAVA毕业设计 2024成品源码+论文+录屏+启动教程 启动教程:https://www.bilibili.com/video/BV1SzbFe7EGZ 项目讲解视频:https://www.bilibili.com/video/BV1Tb421n72S 二次开发教程:https://www.bilibili.com/video/BV18i421i7Dx
"深入探究蠕动流与Brinkman达西定律在COMSOL模拟中的应用",蠕动流、Brinkman 达西定律COMSOL ,蠕动流; Brinkman 达西定律; COMSOL,**利用达西定律与Brinkman模型分析蠕动流现象**
免费JAVA毕业设计 2024成品源码+论文+录屏+启动教程 启动教程:https://www.bilibili.com/video/BV1SzbFe7EGZ 项目讲解视频:https://www.bilibili.com/video/BV1Tb421n72S 二次开发教程:https://www.bilibili.com/video/BV18i421i7Dx
免费JAVA毕业设计 2024成品源码+论文+录屏+启动教程 启动教程:https://www.bilibili.com/video/BV1SzbFe7EGZ 项目讲解视频:https://www.bilibili.com/video/BV1Tb421n72S 二次开发教程:https://www.bilibili.com/video/BV18i421i7Dx
JRT 0287-2023 人工智能算法金融应用信息披露指南.pdf
西门子S7协议纯指令编写源代码,支持多区域数据通信读写:Qx.y与Mx.y的单点操作,Byte、Word、DWORD的全面读写,以及V区浮点数处理,西门子S7协议通信,纯指令编写,不调用dll。 源代码 实现以下功能, 1,对单点读写,Qx.y,Mx.y的写入,Ix.y的读取。 2,对Byte,Word,DWORD的读写,支持读写Q区,I区,M区,V区。 3,对浮点数的读写,支持V区。 以上功能已经在S7 Smart PLC上测试过,带网口的CR40 CR60已支持。 ,西门子S7协议通信;纯指令编写;单点读写;Qx.y、Mx.y写入;Ix.y读取;Byte、Word、DWORD读写;Q区、I区、M区、V区读写;浮点数读写;S7 Smart PLC测试;网口CR40 CR60支持,西门子S7协议通信纯指令编写:PLC多区域读写及浮点数操作实现
matlab绘图 采用PreScan、ROS、Simulink进行自动驾驶控制算法仿真 横向控制采用的是stanley,MPC算法 使用说明 0分支说明 master分支:运行在ros端的控制算法,包括stanley,mpc。 PreScan分支:包含了prescan工程的压缩文件,解压后需要在matlab中添加自定义的ros msg,也就是src/nodes/msgs 配合控制程序,可以直接进行prescan-ros仿真。 1环境说明 PC1:装win10系统;运行prescan2019.2和matlab2019b;ip = 172.16.6.248 PC2:Ubuntu18.04,ros melodic;ip = 172.16.6.70 p.s. PC1和PC2应该处于同一网段下 2PC2(ubuntu18.04)操作说明 clone master分支的代码后 2.1修改PC2的.bashrc文件,向其中添加PC2的ip地址 sudo gedit ~/.bashrc #打开bashrc #在bashrc文件的末尾添加如下两行 export ROS_IP=172.16.
B2B2C2021H5 + 100% PHP8.2 + Laravel10.0
内容概要:本文详细介绍了C++从基础语法、面向对象编程到高级特性等方面的编程要点,包括变量与数据类型、运算符与表达式、控制结构、类与对象、封装、继承、多态等核心概念,并深入探讨了C++在游戏开发、人工智能、操作系统开发等热门领域的具体应用案例。此外,还讲解了C++在模板、异常处理和智能指针方面的高级功能。最后总结了C++在现代科技发展中扮演的重要角色和未来的应用前景。 适合人群:具备一定编程背景的开发者,特别是对C++语言感兴趣的初级至中级程序员。 使用场景及目标:①希望通过本文深入了解C++的各个方面,并在实践中更好地应用;②提升C++编程技能,在涉及高性能计算、嵌入式系统、人工智能等领域时能够得心应手;③掌握最新的C++技术和趋势,为应对未来技术变革做好准备。 其他说明:本文不仅讲述了C++的基本理论知识,还在多个实际案例中展示了如何运用这些知识解决问题,帮助读者更好地理解C++的特点与优势。
Matlab
1.版本:matlab2014/2019a/2024a 2.附赠案例数据可直接运行matlab程序。 3.代码特点:参数化编程、参数可方便更改、代码编程思路清晰、注释明细。 4.适用对象:计算机,电子信息工程、数学等专业的大学生课程设计、期末大作业和毕业设计。
"深入解析S7-200组态王液位串级控制:双容带前馈与反馈的梯形图接线图原理及IO分配与组态画面详解",No.92 S7-200组态王液位串级控制,双容带前馈和反馈 带解释的梯形图接线图原理图图纸,io分配,组态画面 ,S7-200组态王液位;串级控制;双容带前馈和反馈;梯形图接线图原理图;IO分配;组态画面,"S7-200液位串级控制:双容前馈反馈组态原理图及IO分配详解"
1、文件内容:perl-Config-Simple-4.59-15.el7.rpm以及相关依赖 2、文件形式:tar.gz压缩包 3、安装指令: #Step1、解压 tar -zxvf /mnt/data/output/perl-Config-Simple-4.59-15.el7.tar.gz #Step2、进入解压后的目录,执行安装 sudo rpm -ivh *.rpm 4、安装指导:私信博主,全程指导安装
"S7-1200 PLC改造No.173 M7120型平面磨床电气控制系统:原理图、接线图及IO分配与组态画面详解",No.173 S7-1200 MCGS M7120型平面磨床电气控制系统的PLC改造 带解释的梯形图接线图原理图图纸,io分配,组态画面 ,核心关键词:S7-1200 PLC; MCGS M7120型平面磨床; 电气控制系统; 改造; 梯形图接线图原理图; IO分配; 组态画面。,"S7-1200 PLC改造平面磨床电气控制系统方案"
Matlab算法:结构与参数学习在贝叶斯网络构建中的应用,实现因果推断与条件概率计算,数据程序分离,注释详尽易理解,Matlab算法:结构学习、参数学习建个贝叶斯网络 Matlab算法:贝叶斯网络因果推断,通过结构学习、参数学习建立贝叶斯网络,给定证据,获得指定特征的条件概率。 数据程序分开,便于使用,注释详细,助于理解 ,结构学习; 参数学习; 贝叶斯网络; 因果推断; 条件概率; 数据程序分离; 注释详细。,Matlab实现贝叶斯网络结构学习与参数学习算法
1.版本:matlab2014/2019a/2024a 2.附赠案例数据可直接运行matlab程序。 3.代码特点:参数化编程、参数可方便更改、代码编程思路清晰、注释明细。 4.适用对象:计算机,电子信息工程、数学等专业的大学生课程设计、期末大作业和毕业设计。