多线程学习总结----线程创建
1.概念定义
1.1什么是CPU?
(1)CentralProgressingUnit中央处理器,是一块超大规模的集成电路,是一台计算机的运算核心和控制核。
(2)CPU包括运算器,高速缓冲存储器,总线。
(3)它的工作,主要是解释计算机中的指令,和处理计算机软中的数据。它在计算机中起着最重要的作用,构成了系统的控制中心,对各个应用程序进行统一协调和控制。
1.2什么是进程?
一个进程就是一个具有独立功能的应用程序,关于某个数据集合上的一次运行活动。进程是系统进行资源分配和调度的一个独立单位。
简单的来说,就比如我日常生活中,在电脑中打开一个app(如:qq音乐,腾讯视频等)。我就可以看到任务管理器中有一个qq音乐的程序在执行,这就是进程。当我们在打开腾讯视频的时候,就会多一个进程(腾讯视频)。
1.3什么是线程?
线程是进程的实体,属于进程,是CPU调度和分派的基本单位。资源分配给进程,所有线程共享该进程的资源
当我们打开qq音乐后,我们先点击播放一首音乐,这时进程中就会创建一个线程去执行播放功能,然后就能听到music响起了。此时,我们再打开搜索面板,搜索一首XXX音乐。这时播放音乐的线程并未结束,而是由另一个线程去执行搜索动作。(一对多的关系)
1.4多线程和CPU的关系?
单核CPU,在单位时间内,只能执行一个线程任务。也就是说有A和B两个线程要执行的时候,会先执行完A,在去执行B。
多核CPU,在单位时间内,可以执行多个线程任务。如2核CPU,会把A线程交给核1CPU执行,并把B线程交给核2CPU执行,就可以实现真正的并行执行。
1.5什么是并发?什么是并行?
并行:多个CPU实例或是多台机器同时执行一段处理逻辑,是真正的同时。
并发:通过CUP调度算法,让用户看上去同时去执行,实际上从CPU操作层面并不是真正的同时。并发往往需要公共的资源,对公共资源的处理和线程之间的协调是并发的难点。
比如,我如果是个单核的CPU电脑,我现在打开QQ音乐App,点击播放一首音乐。同时,我又打开了英雄联盟,准备开始玩游戏。这时又两个进程,但是单位时间只能执行一个线程任务。为了在打英雄联盟的时候,qq音乐不会停止播放。就会使用CPU调度算法,在英雄联盟和qq音乐来回切换执行(当然是远远快于人的反应时间),此时我们就会有播放音乐和打游戏是同时在执行的假象了。
如果是多核CPU,就可以一个CPU核执行qq音乐,一个执行英雄联盟。
1.6什么是四核八线程?
在买电脑的时候,介绍CPU的时候就会又这么一个参考数值。那到底是啥子意思咯?
上面介绍了,单位时间内一个CPU只能执行一个线程。如果想要在一单位时间内处理超过一个线程是不可能的,除非是有两个CPU的实体单元。多核心技术是将多个一样的CPU放置于一个封装内(或直接将两个CPU做成一个芯片),而英特尔的HT技术是在CPU内部仅复制必要的资源、让CPU模拟成两个线程;也就是一个实体核心,两个逻辑线程,在一单位时间内处理两个线程的工作,模拟实体双核心、双线程运作。
所以,四核八线程就代表着四个CPU,八线程代表每个CPU有两个逻辑线程。最高单位时间执行八个线程工作。
2.多线程生命周期
线程包括5种状态:
1、新建(New):线程对象被创建时,它只会短暂地处于这种状态。此时它已经分配了必须的系统资源,并执行了初始化。例如,Thread thread = new Thread()。
2、就绪(Runnable):称为“可执行状态”。线程对象被创建后,其它线程调用了该对象的start()方法,从而来启动该线程。例如,thread.start()。处于就绪状态的线程,随时可能被CPU调度执行。
3、运行(Running):线程获取CPU权限进行执行。注意:线程只能从就绪状态进入运行状态。
4、阻塞(Blocked):阻塞状态是线程因为某种原因放弃CPU使用权,暂时停止运行。直到线程进入就绪状态,才有机会转到运行状态。阻塞的情况分为三种:
(1)等待阻塞:通过调用线程的wait()方法,让线程等待某工作的完成。
(2)同步阻塞:线程在获取synchronized同步锁失败(因为锁被其他线程占用),它会进入同步阻塞状态。
(3)其他阻塞:通过调用线程的sleep()或发出了I/O请求时,线程会进入到阻塞状态。当sleep()状态超时、join()等待线程终止或是超时。或是I/O处理完毕时,线程重新转入就绪状态。
5.死亡(Dead):线程执行完了或者因异常退出了run()方法,该线程结束生命周期。
3.多线程创建
方式一: package com.my.thread; /** * 继承Thread创建线程 * @作者:onereader * @日期:2018年9月5日 */ public class MyThreadDemo1 extends Thread{ public static void main(String[] args) { MyThreadDemo1 t1 = new MyThreadDemo1(); t1.start(); System.out.println("主线程"); } @Override public void run() { System.out.println("使用继承Thread实现线程创建"); } } 方式二: package com.my.thread; /** * 实现Runnable接口创建接口 * @作者:onereader * @日期:2018年9月5日 */ public class MyThreadDemo2 implements Runnable{ public static void main(String[] args) { MyThreadDemo2 t2 = new MyThreadDemo2(); Thread t = new Thread(t2); t.start(); System.out.println("主线程"); for(int i=1;i<100;i++) { System.out.println("主线程输出:"+i); } } @Override public void run() { System.out.println("Runnable接口实现线程创建"); for(int i=1;i<100;i++) { System.out.println("线程MyThreadDemo2输出:"+i); } } } 方式三: package com.my.thread; import java.util.concurrent.Callable; import java.util.concurrent.FutureTask; /** * 内部类创建线程 * @作者:onereader * @日期:2018年9月5日 */ public class MyThreadDemo3{ static class ThreadDemo implements Callable<String> { @Override public String call() { System.out.println("Hello Thread"); return "Callable return value"; } } public static void main(String[] args) { ThreadDemo threadDemo = new ThreadDemo(); FutureTask<String> futureTask = new FutureTask<String>(threadDemo); Thread thread = new Thread(futureTask); thread.start(); try { System.out.println(futureTask.get()); } catch (Exception e) { e.printStackTrace(); } } }
以上只是个简单的总结,后续会更精彩的哟!