Java并发编程--基础(一)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/LuuvyJune/article/details/85782465

多线程基础

1、线程与进程(面试经常问到)

进程:现在的操作系统几乎都支持多任务执行,对计算机来说,每一个任务就是一个进程。

线程:一个进程可能会派生或者创建很多线程,线程是程序执行的一个路径,每一个线程都有自己的局部变量表、程序计数器(指向正在执行的指令指针)以及各自的生命周期。结合操作系统知识来讲,一个进程中有很多个线程,它们的运行其实和cpu执行时间片有关,因为cpu处理的速度很快,多个线程执行时切换的速度很快,所以看起来像是同时执行(并发的)。

2、线程的创建、启动

创建线程:构造Thread类。

Thread run()源码:

@Override
public void run(){
    
    //如果构造Thread时传递了Runnable,则会执行runnable的run()
    if(target != null){
        target.run();
    }
    //否则需要重写Thread的run()
}

真正的逻辑在run()中,是线程的执行单元,用start()方法启动线程。

实现线程的执行单元有两种方式:

(1)重写Thread的run(),实际上Thread实现了Runnable接口,该run()不能共享,线程A不能把B的run()当做自己的执行单元。

Thread实现了Runnable源码:

//截取了一小段代码

public class Thread implements Runnable {
    /* Make sure registerNatives is the first thing <clinit> does. */
    private static native void registerNatives();
    static {
        registerNatives();
    }

    private volatile String name;
    private int            priority;
    private Thread         threadQ;
    private long           eetop;
    
    //其他属性、方法等
    //......
}

(2)实现Runnable的run(),并将Runnable实例用作构造Thread的参数,可以共享,使用同一个Runnable的实例构造不同的Thread实例。

实现Runnable,将线程的控制和业务逻辑彻底分离开来。

Runnable接口源码:

public interface Runnable {
    /**
     * When an object implementing interface <code>Runnable</code> is used
     * to create a thread, starting the thread causes the object's
     * <code>run</code> method to be called in that separately executing
     * thread
     */
    public abstract void run();
}

 模拟营业大厅叫号机,使用同一个Runnable,资源共享:

/**
 * 模拟营业大厅叫号机,使用同一个Runnable,资源共享
 */

public class TicketRunnable implements Runnable{

    private int index = 1;
    
    private final static int MAX = 50;

    @Override
    public void run() {

        while(index <= MAX){
            System.out.println(Thread.currentThread() + "的号码是" + (index++));
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    public static void main(String args[]){
        
        final TicketRunnable ticketRunnable = new TicketRunnable();
        
        Thread thread1 = new Thread(ticketRunnable,"一号窗口");
        
        Thread thread2 = new Thread(ticketRunnable,"二号窗口");
        
        Thread thread3 = new Thread(ticketRunnable,"三号窗口");
        
        Thread thread4 = new Thread(ticketRunnable,"四号窗口");
        
        thread1.start();
        thread2.start();
        thread3.start();
        thread4.start();
    }
}
 

3、线程的生命周期

线程生命周期状态图:

  • new 不处于执行状态,没有调用start()启动该线程。
  • runnable:此时已经在JVM的线程中创建了一个线程,调用了start(),执行与否需要听令于CPU的调度。
  • running:cpu通过轮询或者其他方式从任务队列中选中线程,开始真正执行自己的逻辑代码。

此时可能发生如下状态转变:

(1)调用stop方法或者判断某个逻辑标识-->terminated(结束)

(2)调用sleep或者wait而进入wait set-->blocked(阻塞)

(3)获取某个锁资源,加入到该锁的阻塞队列中-->blocked

(4)cpu调度器轮询该线程放弃执行-->runnable

(5)调用yield(),放弃cpu执行权-->runnable

  • blocked:阻塞状态。

此时可以切换以下状态:

(1)调用stop方法或者意外死亡-->terminated(结束)

(2)线程阻塞结束,如读取到想要的数据字节-->runnable

(3)线程完成了指定时间的休眠-->runnable

(4)wait中线程被其他线程notify/notifyAll-->runnable

(5)线程获取到了某个锁资源-->runnable

(6)线程阻塞过程中被打断,如其他线程调用interrupt()-->runnable

  • terminated:最终状态。

4、Thread API

(1)sleep():给定一个休眠的时间,以系统的定时器和调度器的精度为准,不会放弃monitor锁的所有权

TimeUnit可代替sleep

(2)yield():提醒调度器放弃当前cpu资源,若当前资源不紧张,调度器会忽略这种提醒,线程running-->runnable

(3)interrupt():

一般来讲,调用这些方法会使得当前线程进入阻塞状态:

  • Object的wait方法
  • Thread的sleep方法
  • Thread的join方法
  • InterruptibleChannel的io操作
  • Selector的wakeup方法

另外一个线程调用被阻塞线程的interrupt方法,会打断这种阻塞,称为可中断方法。

一个线程的阻塞状态被打断,会抛出一个InterruptedException。

(4)isInterrupted():Thread的一个成员方法,判断当前线程是否被中断,仅仅是对interrupt标识的判断,可中断方法如sleep()获得中断信号(捕获到InterruptredException)之后会擦除interrupt标识。

(5)interrupted():是一个静态的方法,也用于判断当前线程是否被中断,调用该方法会直接擦除interrupt标识,若当前线程被打断,第一次调用interrupted()会返回true并立即擦除了interrupt标识,第二次及以后的调用都会返回false,除非在此期间又一次被打断。

(6)join():与sleep一样是可中断方法。join某个线程A,会使得当前线程B进入等待,直到线程A结束生命周期,或者到达给定的时间。通常都是main线程等到其他多个线程执行完毕后再继续执行,其他多个线程之间并不需要互相等待。

5、关闭线程

(1)线程运行结束,完成使命正常退出。

(2)捕获中断信号关闭线程。

(3)使用volatile修饰的flag开关控制。

(4)RuntimeException 异常退出。

(5)进程假死(某个线程阻塞,死锁)。

猜你喜欢

转载自blog.csdn.net/LuuvyJune/article/details/85782465
今日推荐