文档章节

多线程

树上的窝
 树上的窝
发布于 2017/05/06 16:48
字数 1648
阅读 5
收藏 0

一、进程与线程

     一个进程就是一个应用程序某个关于集合数据上的一次运行活动,进程是系统进行资源分配和调度的一个独立单位,进程可能有多个线程。

     线程是进程的一个实体,是CPU进行调度和分配的基本单位。它是比进程更小的能独立运行的基本单位.线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(如程序计数器,一组寄存器和栈),但是它可与同属一个进程的其他的线程共享进程所拥有的全部资源.

二、并行、并发、串行

你吃饭吃到一半,电话来了,你一直到吃完了以后才去接,是串行。这就说明你不支持并发也不支持并行。
你吃饭吃到一半,电话来了,你停了下来接了电话,接完后继续吃饭,这说明你支持并发。
你吃饭吃到一半,电话来了,你一边打电话一边吃饭,这说明你支持并行。

并发的关键是你有处理多个任务的能力,不一定要同时。
并行的关键是你有同时处理多个任务的能力。

所以我认为它们最关键的点就是:是否是『同时』。

三、多线程

     线程包含7种状态:出生、就绪、运行、等待、休眠、阻塞、死亡。

新建状态(New):当线程对象对创建后,即进入了新建状态,如:Thread t = new MyThread();

就绪状态(Runnable):当调用线程对象的start()方法(t.start();),线程即进入就绪状态。处于就绪状态的线程,只是说明此线程已经做好了准备,随时等待CPU调度执行,并不是说执行了t.start()此线程立即就会执行;

运行状态(Running):当CPU开始调度处于就绪状态的线程时,此时线程才得以真正执行,即进入到运行状态。注:就绪状态是进入到运行状态的唯一入口,也就是说,线程要想进入运行状态执行,首先必须处于就绪状态中;

阻塞状态(Blocked):处于运行状态中的线程由于某种原因,暂时放弃对CPU的使用权,停止执行,此时进入阻塞状态,直到其进入到就绪状态,才有机会再次被CPU调用以进入到运行状态。根据阻塞产生的原因不同,阻塞状态又可以分为三种:

1.等待阻塞 -- 运行状态中的线程执行wait()方法,使本线程进入到等待阻塞状态,需要调用notify()方法将其唤醒;

2.同步阻塞 -- 线程在获取synchronized同步锁失败(因为锁被其它线程所占用),它会进入同步阻塞状态;

3.其他阻塞 -- 通过调用线程的sleep()或join()或发出了I/O请求时,线程会进入到阻塞状态。当sleep()状态超时、join()等待线程终止或者超时、或者I/O处理完毕时,线程重新转入就绪状态。

死亡状态(Dead):线程执行完了或者因异常退出了run()方法,该线程结束生命周期。

四、sleep()和wait()方法的区别

        调用sleep()方法,使线程进入睡眠状态,当达到设定时间就会自动执行,且不会释放系统资源。

        调用wait()方法,线程进入等待状态,需要调用notify()方法将其唤醒,在等待时会释放系统资源。

五、创建多线程

          多线程的创建的最常见有两种方式

第一种是直接继承Thread类,并重写run()方法

 class MyThread extends Thread {
     
     private int i = 0;
      @Override
     public void run() {
         for (i = 0; i < 100; i++) {
             System.out.println(Thread.currentThread().getName() + " " + i);
          }
     }
 }


 public class ThreadTest {
     public static void main(String[] args) {
        for (int i = 0; i < 100; i++) {
             System.out.println(Thread.currentThread().getName() + " " + i);
            if (i == 30) {
                  Thread myThread1 = new MyThread();// 创建一个新的线程  myThread1  此线程进入新建状态
                 Thread myThread2 = new MyThread(); // 创建一个新的线程 myThread2 此线程进入新建状态
                 myThread1.start();                 // 调用start()方法使得线程进入就绪状态
                 myThread2.start();                 // 调用start()方法使得线程进入就绪状态
         }
     }
 }

第二种实现Runnable接口,并重写run()方法

class MyRunnable implements Runnable {
    private int i = 0;
 
      @Override
     public void run() {
         for (i = 0; i < 100; i++) {
            System.out.println(Thread.currentThread().getName() + " " + i);
          }
     }
 }


public class ThreadTest {

    public static void main(String[] args) {
        for (int i = 0; i < 100; i++) {
             System.out.println(Thread.currentThread().getName() + " " + i);
            if (i == 30) {
              Runnable myRunnable = new MyRunnable(); // 创建一个Runnable实现类的对象
              Thread thread1 = new Thread(myRunnable); // 将myRunnable作为Thread target创建新的线程
              Thread thread2 = new Thread(myRunnable);
              thread1.start();                         // 调用start()方法使得线程进入就绪状态
              thread2.start();
             }
         }
    }
 }

六、关键字 synchronized

        线程安全:实质上线程安全问题来源于多个线程同时处理单一对象。一个线程对多条语句只执行一部分,还没有执行完,另一线程参与进来执行,导致共享数据的错误。

         解决方法:对多条操作共享数据的语句,只能让一个线程执行完,再让其他线程执行。(同步代码块)

同步的前提:

                    1、必须要有两个或者两个以上的线程;

                    2、必须是多个线程使用同一把锁;

  好处:解决多线程的安全问题

  弊端:必须对锁进行判断,较为耗费资源

synchronized  修饰一个方法或代码块,能保证同一时刻只有一个线程在执行。

   一、当两个并发线程访问同一个对象object中的这个synchronized(this)同步代码块时,一个时间内只能有一个线程得到执行。另一个线程必须等待当前线程执行完这个代码块以后才能执行该代码块。

     二、然而,当一个线程访问object的一个synchronized(this)同步代码块时,另一个线程仍然可以访问该object中的非synchronized(this)同步代码块。

     三、尤其关键的是,当一个线程访问object的一个synchronized(this)同步代码块时,其他线程对object中所有其它synchronized(this)同步代码块的访问将被阻塞。

     四、也就是说,当一个线程访问object的一个synchronized(this)同步代码块时,它就获得了这个object的对象锁。结果,其它线程对该object对象所有同步代码部分的访问都被暂时阻塞。

     五、以上规则对其它对象锁同样适用.

 

 

© 著作权归作者所有

树上的窝
粉丝 1
博文 15
码字总数 6762
作品 0
深圳
程序员
私信 提问

暂无文章

JWT学习总结

官方 https://jwt.io 英文原版 https://www.ietf.org/rfc/rfc7519.txt 或 https://tools.ietf.org/html/rfc7519 中文翻译 https://www.jianshu.com/p/10f5161dd9df 1. 概述 JSON Web Token(......

冷基
26分钟前
2
0
AOP的学习(1)

AOP 理解AOP编程思想(面向方法、面向切面) spring AOP的概念 方面 -- 功能 目标 -- 原有方法 通知 -- 对原有方法增强的方法 连接点 -- 可以用来连接通知的地方(方法) 切入点 -- 将用来插入...

太猪-YJ
今天
4
0
一张图看懂亮度、明度、光度、光亮度、明亮度

亮度、明度、光亮度,Luminance和Brightness、lightness其实都是一个意思,只是起名字太难了。 提出一个颜色模型后,由于明度的取值与别人的不同,为了表示区别所以就另想一个词而已。 因此在...

linsk1998
昨天
8
0
Python应用:python链表示例

前言 python链表应用源码示例,需要用到python os模块方法、函数和类的应用。 首先,先简单的来了解下什么是链表?链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是...

python小白1
昨天
4
0
Source Insight加载源码

Source Insight是一个图形化的源代码查看工具(当然也可以作为编译工具)。如果一个项目的源代码较多,此工具可以很方便地查找到源代码自建的依赖关系。 1.创建工程 下图为Snort源代码的文件...

天王盖地虎626
昨天
5
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部