多线程学习总结(一)

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();
            }
        }
}
以上只是个简单的总结,后续会更精彩的哟!

猜你喜欢

转载自www.cnblogs.com/one-reader/p/11305920.html
今日推荐