Java之Thread浅谈

2018-06-07  本文已影响0人  MIRROR1217

进程与线程

什么是进程?进程是操作系统结构的基础,是程序在一个数据集合上运行的过程,是系统进行资源分配和调度的基本单位。进程可以被看作程序的实体,同样,它也是线程的容器。

什么是线程?线程是操作系统调度的最小单元,也叫作轻量级进程。在一个进程中可以创建多个线程,这些线程都拥有各自的计数器、堆栈和局部变量等属性,并且能够访问共享的内存变量。

线程的状态

线程的简单应用

上面已经说过,线程有多种状态,那么为什么需要这几种状态?或者说哪些情况会进入到这些状态?下面我们举例说明。

Thread thread = new Thread(new Runnable() {
        @Override
        public void run() {         
            //do something...   
    }
});
System.out.println(thread.getState());

我们看打印的结果:Thread-0:NEW,可以证明该线程处于New状态。

Thread thread = new Thread(new Runnable() {
        @Override
        public void run() {         
            
    }
});
thread.start();
System.out.println(thread.getState());

首先看下打印的结果:Thread-0:RUNNABLE。线程创建完成后我们调用start方法,线程会进入Runnable状态。

这里解释下什么叫阻塞状态?运行的线程在获取对象的同步锁时,若该同步锁被别的线程占用,该线程将进入阻塞状态,如下示例。

public class Thread9 {

    static Object object = new Object();
    
    public static void main(String[] args) {
        ThreadA threadA = new ThreadA();
        ThreadB threadB = new ThreadB();
        threadA.setName("threadA");
        threadB.setName("threadB");
        threadA.start();
        try {
            Thread.sleep(10);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        threadB.start();
        System.out.println(threadA.getName() + ":" + threadA.getState());
        System.out.println(threadB.getName() + ":" + threadB.getState());

    }
    
    static class ThreadA extends Thread{
        
        @Override
        public void run() {
            synchronized (object) {
                while(true) {
                }
            }
        };
    }
    
   static class ThreadB extends Thread{
        
        @Override
        public void run() {
            synchronized (object) {
                System.out.println("ThreadB");
            }
        };
    }

}

打印结果:

threadA:RUNNABLE
threadB:BLOCKED

上面的例子中,开启两个线程ABA、B线程的run方法中获取同一对象的同步锁,由于A线程一直持有Object对象,B线程的任务无法进行,会进入阻塞状态。当A线程任务完成或出现异常将不再持有该对象时,B线程将进入到Runnable状态。

线程暂时不活动,并且不运行任何代码,调用wait()join()(实际上也是调用wait()方法)方法可进入该状态,调用notify()notifyAll()方法解除状态,示例如下。

调用join()方法

package thread;

public class JoinTest {

    public static void main(String[] args) throws InterruptedException{
        Thread1 thread1 = new Thread1();
        thread1.setName("Thread-1");
        thread1.start();
        System.out.println("begin");
        Thread.sleep(2000);
        System.out.println(thread1.getName() + ":" + thread1.getState());
    }
    
    static class Thread1 extends Thread {
        
        @Override
        public void run(){
            
            Thread thread2 = new Thread(new Runnable() {
                
                @Override
                public void run() {
                    
                    for (int i = 0; i < 5; i++) {
                        try {
                            Thread.sleep(1000);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        System.out.println("Thread-2:running");
                    } 
                }
            });
            thread2.setName("Thread-2");
            thread2.start();
            try {
                thread2.join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("end");
        }
    }
    
}

打印结果:

begin
Thread-2:running
Thread-1:WAITING
Thread-2:running
Thread-2:running
Thread-2:running
Thread-2:running
end

在线程1中再开启一个线程2,线程2开始后调用join()方法,然后查看线程1的状态。

调用wait()方法

package thread;

import java.util.concurrent.TimeUnit;

public class WaitTest{
    

    public synchronized void waittest() throws InterruptedException {
        System.out.println("start");
        wait();
        System.out.println("over");
    }
    
    public synchronized void notifyTest() {
        notifyAll();
    }
    
    public static void main(String[] args) throws InterruptedException{
        WaitTest waitTest = new WaitTest();
        Thread mainThread = Thread.currentThread();
        MyThread myThread = new MyThread(mainThread,waitTest);
        mainThread.setName("Thread-main");
        myThread.setName("Thread-0");
        myThread.start();
        waitTest.waittest();
        
    }
    
    static class MyThread extends Thread{
        
        Thread thread;
        WaitTest waitTest;
        
        public MyThread(Thread thread,WaitTest waitTest) {
            this.thread = thread;
            this.waitTest = waitTest;
        }
        
        @Override
        public void run() {
            
            try {
                Thread.sleep(200);
            } catch (InterruptedException e1) {
                e1.printStackTrace();
            }
            
            System.out.println(thread.getName() 
                    + ":" + thread.getState());
            
            int i = 0;
            do {
                i++;
                try { 
                    TimeUnit.SECONDS.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(this.currentThread().getName() 
                        + ":" + this.currentThread().getState());
                
            } while (i < 5);
            
            waitTest.notifyTest();
        }
        
    }

}

打印结果:

start
Thread-main:WAITING
Thread-0:RUNNABLE
Thread-0:RUNNABLE
Thread-0:RUNNABLE
Thread-0:RUNNABLE
Thread-0:RUNNABLE
over

开启一个新线程,然后主线程调用wait()方法(必须使用同步字synchronized加锁,否则会报异常),查看主线程的状态。

通过上面两个示例我们可以看到,调用wait()join()方法都可以使线程进入WAITING状态,但是它们两者是有区别的(它们的区别以后会讲到,这里就不详细比较了)。

Timed waitingWaiting的不同之处在于,Timed waiting有时间限制,时间到了之后将自行解除该状态。

package thread;

public class TimeWaitIngTest {

    public static void main(String[] args) {
        
        ThreadA threadA = new ThreadA();
        ThreadA threadB = new ThreadA();
        ThreadA threadC = new ThreadA();
        threadA.setName("thread-A");
        threadB.setName("thread-B");
        threadC.setName("thread-C");
        threadA.start();
        threadB.start();
        threadC.start();
        
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        
        System.out.println(threadA.getName() 
                + ":" + threadA.getState());
        
        System.out.println(threadB.getName() 
                + ":" + threadB.getState());
        
        System.out.println(threadC.getName() 
                + ":" + threadC.getState());

        
    }
    
    static class ThreadA extends Thread{
        
        @Override
        public void run() {
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    
   static class ThreadB extends Thread{
        
        @Override
        public void run() {
            try {
                wait(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
   
   static class ThreadC extends Thread{
        
        @Override
        public void run() {
            try {
                join(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

}

打印结果:

thread-A:TIMED_WAITING
thread-B:TIMED_WAITING
thread-C:TIMED_WAITING

开启三个线程,分别调用sleep(long)wait(long)join(long)方法,看这三个线程的状态。

package thread;

public class TerminatedTest {

    public static void main(String[] args) throws InterruptedException{
        
        MyThread myThread = new MyThread();
        myThread.setName("MyThread");
        System.out.println(myThread.getName() 
                + ":" + myThread.getState());
        myThread.start();
        Thread.sleep(10);
        System.out.println(myThread.getName() 
                + ":" + myThread.getState());

    }
    
    static class MyThread extends Thread{
        
        @Override
        public void run() {
            
        }
    }

}

打印结果:

MyThread:NEW
MyThread:TERMINATED

新建一个线程,然后执行,看线程的状态变化。

综上所诉,线程一般有6种状态,下面用一张图来总结


线程状态
上一篇下一篇

猜你喜欢

热点阅读