zoukankan      html  css  js  c++  java
  • java多线程知识点总结

    1.几个基本的概念

    进程(Process):

    一个程序运行起来时在内存中开辟一段空间用来运行程序,这段空间包括heap、stack、data segment和code segment。例如,开一个QQ就表明开了一个QQ进程。

    线程(Thread):

    每个进程中都至少有一个线程。线程是指程序中代码运行时的运行路径,一个线程表示一条路径。例如QQ进程中,发送消息、接收消息、接收文件、发送文件等各种独立的功能都需要一个线程来执行。

    进程和线程的区别:

    从资源的角度来考虑,进程主要考虑的是CPU和内存,而线程主要考虑的是CPU的调度,某进程中的各个线程之间可以共享这个进程的很多资源。

    从粒度粗细来考虑,进程的粒度较粗,进程上下文切换时消耗的CPU资源较多。线程的粒度要小的多,虽然线程也会切换,但因为共享进程的上下文,相比进程上下文切换而言,同进程内的线程切换时消耗的资源要小的多的多。在JAVA中,除了java运行时启动的JVM是一个进程,其他所有任务都以线程的方式执行,也就是说java应用程序是单进程的,甚至可以说没有进程的概念。

    线程组(ThreadGroup):

    线程组提供了一些批量管理线程的方法,因此通过将线程加入到线程组中,可以更方便的管理这些线程

    线程的状态

    就绪态、运行态、睡眠态。还可以分为存活和死亡,死亡表示线程结束,非死亡则存活,因此存活包含就绪、运行、睡眠。

     

    java thread的运行周期中, 有几种状态, 在 java.lang.Thread.State 中有详细定义和说明:

    NEW 状态是指线程刚创建, 尚未启动

    RUNNABLE 状态是线程正在正常运行中, 当然可能会有某种耗时计算/IO等待的操作/CPU时间片切换等, 这个状态下发生的等待一般是其他系统资源, 而不是锁, Sleep等

    BLOCKED  这个状态下, 是在多个线程有同步操作的场景, 比如正在等待另一个线程的synchronized 块的执行释放, 或者可重入的 synchronized块里别人调用wait() 方法, 也就是这里是线程在等待进入临界区

    WAITING  这个状态下是指线程拥有了某个锁之后, 调用了他的wait方法, 等待其他线程/锁拥有者调用 notify / notifyAll 一遍该线程可以继续下一步操作, 这里要区分 BLOCKED 和 WATING 的区别, 一个是在临界点外面等待进入, 一个是在理解点里面wait等待别人notify, 线程调用了join方法 join了另外的线程的时候, 也会进入WAITING状态, 等待被他join的线程执行结束

    TIMED_WAITING  这个状态就是有限的(时间限制)的WAITING, 一般出现在调用wait(long), join(long)等情况下, 另外一个线程sleep后, 也会进入TIMED_WAITING状态

    TERMINATED 这个状态下表示 该线程的run方法已经执行完毕了, 基本上就等于死亡了(当时如果线程被持久持有, 可能不会被回收)

    中断睡眠(interrupt):

    将线程从睡眠态强制唤醒,唤醒后线程将进入就绪队列等待cpu调度。

    并发操作:

    多个线程同时操作一个资源。这会带来多线程安全问题,解决方法是使用线程同步。

    线程同步:

    让线程中的某些任务原子化,即要么全部执行完毕,要么不开始执行。通过互斥锁来实现同步,通过监视这个互斥锁是否被谁持有来决定是否从睡眠态转为就绪态(即从线程池中出去),也就是是否有资格去获取cpu的执行权。线程同步解决了线程安全的问题,但降低了程序的效率。

    死锁:

    线程全睡眠了无法被唤醒,导致程序卡死在某一处无法再执行下去。典型的是两个同步线程,线程1持有A锁,且等待B锁,但线程2持有B锁且等待A锁,这样的僵局会造成死锁。但需要注意的是,死锁并非都是因为僵局,只要两边的线程都无法继续向下执行代码(或者两边的线程池都无法被唤醒,这是等价的概念,因为锁等待也会让进程进入睡眠态),则都是死锁

    还需需要明确的一个关键点是:CPU对就绪队列中每个线程的调度是随机的(对我们人类来说),且分配的时间片也是随机的(对人类来说)。

    2.创建线程的两种方法

    继承Thread类

    创建线程方式一:

    1. 继承Thread类(在java.lang包中),并重写该类的run()方法,其中run()方法即线程需要执行的任务代码。
    2. 然后new出这个类对象。这表示创建线程对象。
    3. 调用start()方法开启线程来执行任务(start()方法会调用run()以便执行任务)。
    class MyThread extends Thread {
        String name;
        String gender;
    
        MyThread(String name,String gender){
            this.name = name;
            this.gender = gender;
        }
    
        public void run(){
            int i = 0;
            while(i<=20) {
                //除了主线程main,其余线程从0开始编号,currentThread()获取的是当前线程对象
                System.out.println(Thread.currentThread().getName()+"-----"+i+"------"+name+"------"+gender);
                i++;
            }
        }
    }
    
    public class CreateThread {
        public static void main(String[] args) {
            MyThread mt1 = new MyThread("malong","Male");
            MyThread mt2 = new MyThread("Gaoxiao","Female");
    
            mt1.start();
            mt2.start();
            System.out.println("main thread over");
        }
    }
    View Code

    创建线程方式二:

    1. 实现Runnable接口,并重写run()方法。
    2. 创建子类对象。
    3. 创建Thread对象来创建线程对象,并将实现了Runnable接口的对象作为参数传递给Thread()构造方法。
    4. 调用start()方法开启线程来执行run()中的任务。
    class MyThread implements Runnable {
        String name;
        String gender;
    
        MyThread(String name,String gender){
            this.name = name;
            this.gender = gender;
        }
    
        public void run(){
            int i = 0;
            while(i<=200) {
                System.out.println(Thread.currentThread().getName()+"-----"+i);
                i++;
            }
        }
    }
    
    public class CreateThread2 {
        public static void main(String[] args) {
            //创建子类对象
            MyThread mt = new MyThread("malong","Male");
            //创建线程对象
            Thread th1 = new Thread(mt);
            Thread th2 = new Thread(mt);
    
            th1.start();
            th2.start();
            System.out.println("main thread over");
        }
    }
    View Code

    这两种创建线程的方法,无疑第二种(实现Runnable接口)要好一些,因为第一种创建方法继承了Thread后就无法继承其他父类。

  • 相关阅读:
    动手动脑
    选课1.0
    四则运算
    JAVA异常处理机制资料整理
    JAVA学习日报(快乐作业) 10.27
    JAVA学习日报(快乐作业) 10.20
    JAVA学习日报 9/30
    JAVA学习日报 9/28
    JAVA学习日报 9/27
    JAVA学习日报 9/26
  • 原文地址:https://www.cnblogs.com/alter888/p/9932754.html
Copyright © 2011-2022 走看看