【Java】多线程基础

线程的状态

状态名称 说明
new 初始状态:线程被构建,但没有调用start()方法
runnable 运行状态:就绪和运行统称“运行中”
blocked 阻塞状态:线程阻塞于锁
waiting 等待状态:线程进入等待状态,需要等待其他线程通知或中断
time_waiting 超时等待状态:指定时间自行返回
terminated 终止状态:线程已执行完毕

1. 线程创建后,调用start()开始运行,进入运行状态;
2. 执行wait()方法后,进入等待状态;
3. 进入等待状态的线程需要其他线程通知才能返回运行状态;
4. 如果是超时等待状态,超时后会返回运行状态;
5. 调用同步方式,没有获得锁(synchronized),则进入阻塞状态;
6. 如果是锁是Lock接口的,则进入等待状态;
7. 执行Runnable的run()后,进入终止状态;

启动 & 终止

构造线程

private void init(String name,ThreadGroup g,Runnable target){
    if(name == null){ 
        throw new NullPointerException("name cannot be null")
    }
    //当前线程为父线程
    Thread parent = currentThread(); 
    this.group = g;
    this.daemon = parent.isDaemon();
    this.priority = parent.getPriority();
    this.name = name.toCharArray();
    this.target = target;
    setPriority(priority);
    //复制父线程的InheritableThreadLocal
    if(parent.inheritableThreadLocals != null){
        this.inheritableThreadLocals = ThreadLocal.createInheritedMap(parent.inheritableThreadLocals);
    }
    //分配线程ID
    tid = nextThreadID(); 
}

启动线程:调用start()方法即可启动线程

终止线程

public static void main(String[] args)throws Exception{
    Runner one = new Runner();
    Thread countThread = new Thread(one,"CountThread");
    countThread.start();
    TimeUnit.SECONDS.sleep(1); //睡眠1秒,main线程对CountThread进行中断,使countThread能够感知中断而结束
    countThread.interrupt();

    Runner two = new Runner();
    countThread = new Thread(two,"CountThread");
    countThread.start();
    TimeUnit.SECONDS.sleep(1); //睡眠1秒,main线程Runner two进行cancel,使countThread能够感知on为false而结束
    two.cancel();
}

private static class Runner implements Runnable{
    private long i;
    private volatile boolean on = true;
    @Override
    public void run(){
        while(on && !Thread.currentThread().isInterrupted()){
            i++;
        }
        System.out.println("Count i = " + i);
    }
    public void cancel(){
        on = false;
    }
}

线程间通信

等待 / 通知 机制

static boolean flag = true;
static Object lock = new Object();

public static main(String[] args)throws Exception{
    Thread waitThread = new Thread(new Wait(),"WaitThread");
    waitThread.start();
    TimeUnit.SECONDS.sleep(1);
    Thread notifyThread = new Thread(new Notify(),"NotifyThread");
    notifyThread.start();
}

static class Wait implements Runnable{
    public void run(){
        synchronized(lock){
            while(flag){
                try{
                    System.out.println(Thread.currentThread() + " wait");
                    lock.wait();
                }catch(InterruptedException e){ }
            }
            System.out.println(Thread.currentThread() + " run");
        }
    }
}

static class Notity implements Runnable{
    public void run(){
        synchronized(lock){
            System.out.println(Thread.currentThread() + " notify");
            lock.notifyAll();
            flag = false;
            SleepUtils.senond(5);
        }
        synchronized(lock){
            System.out.println(Thread.currentThread() + " hold lock again");
        }
    }
}

管道输入 / 输出流

public static void main(String[] args)throws Exception{
    PipedWriter out = new PipedWriter();
    PipedReader in = new PipedReader();
    out.connect(in);
    Thread printThread = new Thread(new Print(in),"PrintThread");
    printThread.start();

    int receive = 0;
    try{
        while((receive = System.in.read()) != -1){
            out.write(receive);
        }
    }finally{
        out.close();
    }
}

static class Print implements Runnable{
    private PipedReader in;
    public Print(PipedReader in){
        this.in = in;
    }
    public void run(){
        int receive = 0;
        try{
            while((receive = in.read) != -1){
                System.out.print((char)receive);
            }
        }catch(IOException e){ }
    }
}

Thread.join()

线程A执行thread.join():线程A等待thread线程终止后才从thread.join()返回

public static void main(String[] args)throws Exception{
    Thread previous = Thread.currentThread();
    for(int i = 0; i < 10; i++){
        Thread thread = new Thread(new Domino(previous),String.valueOf(i));
        thread.start();
        previous = thread;
    }
    TimeUnit.SECONDS.sleep(5);
    System.out.println(Thread.currentThread().getName() + " terminate.");
}

static class Domino implements Runnable{
    private Thread thread;
    public Domino(Thread thread){
        this.thread = thread;
    }
    public void run(){
        try{
            thread.join();
        }catch(InterruptedException e){ }
        System.out.println(Thread.currentThread().getName() + " terminate.");
    }
}

ThreadLocal

public class Profiler{
    private static final ThreadLocal<long> TIME_THREADLOCAL = new ThreadLocal<long>(){
        protected Long initialValue(){
            return System.currentTimeMillis();
        }
    }

    public static final void begin(){
        TIME_THREADLOCAL.set(System.currentTimeMillis());
    }

    public static final long end(){
        return System.currentTimeMillis() - TIME_THREADLOCAL.get();
    }

    public static void main(String[] args)throws Exception{
        Profiler.begin();
        TimeUnit.SECONDS.sleep(1);
        System.out.println("Cost: " + Profiler.end() + " mills");
    }
}

小结

线程的生命周期中有6中不同状态,指定时刻,只能处在一个状态;

线程的相互配合需要线程间的通信,等待/通知机制可以得到生产者消费者的效果,管道输入输出流可以在线程间进行数据传输,Thread.join()有等待插入线程完成的效果,ThreadLocal是附带在线程上的变量,可以让线程存储查看值

猜你喜欢

转载自blog.csdn.net/Francis123580/article/details/80561696