简单点聊聊什么是多线程

前言
最近在了解一些多线程方面的知识,看了豆瓣上许多多线程的书,打算以《图解Java多线程设计模式》为教程书,这本我大学时就很喜欢的作者的书入手,一步一步以我的理解方式给大家梳理多线程领域的一些设计思路,也是为了能够重新拾起这些知识,大家也可自行下载电子书,🔗在我的云盘上,链接在文末,大家需要的可以自取
Java多线程
第一篇读书笔记,我首先总结并梳理了一下几个关于java多线程的基础
- 什么是线程
- 线程启动
- 线程暂停
- 线程互斥
- 线程协作
什么是线程
james是个喜欢足球的大男孩,他平时是个很听话的男孩,她的老妈告诉他,每一天都要给自己做好计划,所以james每天睡觉前都会事先规划好第二天做事的计划
起床洗漱
和母亲吃早饭去兄弟浓眉哥家等浓眉
和兄弟浓眉哥一起去上课
……
训练足球
和兄弟浓眉哥一起去麦当劳
和浓眉哥一起回家复习功课
休息
然而不幸的是,期中考试成绩出来了,james的英语成绩那叫一个惨啊,他的好兄弟浓眉也没好哪去,所以两个为了补考能过,商量好每天要多腾出些时间用来复习,于是james的每日计划变了
起床洗漱
和母亲吃早饭
去兄弟浓眉家哥等待的同时复习英语听力
…
训练足球
和浓眉哥分别买了一份麦当劳并回家
复习功课
休息
终于,这两个难兄难弟的补考终于及格过了,可以明显看出,他们在改变计划之后,做事的效率就提升了。那么在生活中想必我们也和james一样认真做一件事情时,我们一般会按照一定的步骤来来,比如先做什么,再做什么,接着做什么,一步步完成任务,无论中间处理事务的过程有多么复杂,只要我们的行为是符合逻辑的,是对的,一切只是时间的问题,最终都会得到结果,这就是单线程处理事务的雏形,但是当有一天我们发现自己完成任务的时间太长,需要提高效率时,往往会选择将一些时间线上不会相互影响的事情进行并行处理,这就是多线程处理事务的雏形,我们在大学时代阅读代码,写程序基本都不会考虑多线程,但是多线程在实际生产环境下确实不可或缺的,它能有效解放多核的生产力,提升数据处理的效率
线程启动
下面我们启动一个线程试试在Java中,我们可以通过两种方法启动
- 利用Thread类的子类实例启动
public class InitThread extends Thread{ @Override public void run(){for(int i=0;i<1000;++i){System.out.println(“james”);} } public static void main(String[] args) { InitThread it = new InitThread(); it.start(); for (int i=0;i<1000;++i) { System.out.println(“rucy”); } }
}
- 利用Runnable接口的事先类的实例启动
public class InitThread2 implements Runnable{ @Override public void run() { for(int i=0;i<1000;++i){ System.out.println(“james”); } }public static void main(String[] args) { InitThread1 it = new InitThread1(); it.start(); for (int i=0;i<1000;++i) { System.out.println(“rucy”); } }
无论那种启动方式,都可以在控制台看到,”james”和”rucy”两个单词是交替打印的,这是因为这个程序不仅启动了main函数本身这个主线程,在main函数中也启动了一个it线程,随后主线程终止,然而整个程序并没有结束,it线程还在执行,等到所有字符都打印出来后,整个程序才算结束
线程暂停
想要线程能够暂停也很简单,我们只需要加入一个Sleep()函数,就可以让处理该线程的时间片时间延长,运行后每次"james"字符输出的空隙时间都为1s
@Override
public void run() { for(int i=0;i<1000;++i){//休眠1000毫秒try { Thread.sleep(1000); }catch (InterruptedException e) {e.printStackTrace(); } System.out.println(“james”); }
}
线程互斥
线程的互斥一直都是多线程问题中最复杂也最难的问题,需要结合不同场景分析,但是最基础的一点就是,要防止多个线程不会异步的去访问一块数据,那么我们必须保证这些线程之间对数据的访问是同步的,所以我们需要一把锁锁住这个线程的行为,可以看如下代码示例
public class SynchronizedTest { public static void main(String[] args){ Thread thread1 = new Thread(new Runnable(){ @Override public void run() { addJ1(); } },”thread1”); Thread thread2 = new Thread(new Runnable(){ @Override public void run() { addJ2(); } },”thread2”); thread1.start(); thread2.start(); } //线程1的行为 public static synchronized void addJ1(){ int i = 5; while (i— > 0) { System.out.println(“james在写作业”); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } } //线程2的行为 public static synchronized void addJ2(){ int i = 5; while(i— > 0) { System.out.println(“james在睡懒觉”); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } }}}
可以看到在每个线程的要执行的方法前加上synchronized关键字可以防止这些线程异步的执行这些方法,大家可以将这个关键字去掉试试,可以看到james边写作业边睡懒觉,很强!
线程协作
线程协作这个部分涉及的内容比较多,但主要还是涉及到几个方法,分别是wait,notify,notifyAll方法,我们先了解下等待队列,每一个对象实例都会有一个等待队列,在调用wait方法之后,这个实例的线程就会停留在这个空间里,如果没有其他线程唤醒,那么这个实例线程就会一直阻塞在队列里休眠,这里有几个方法,大家可以了解一下
- wait方法:将线程放入等待队列
- notify方法:从等待队列中取出线程
- notifyAll:从等待队列中取出所有线程
新人入驻微信公众号求关注,主要分享一些计算机基础知识和刷题技巧,关注即可获得我精心准备的技术电子书资源一份

本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
