美文网首页
Java之Thread浅谈

Java之Thread浅谈

作者: MIRROR1217 | 来源:发表于2018-06-07 17:40 被阅读0次

    进程与线程

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

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

    线程的状态

    • New:新创建的状态。线程被创建,还没有调用start方法,在线程运行之前还有一些基础工作要做。
    • Runnable:可运行状态。一旦调用start方法,线程就处于Runnable状态。一个可运行的线程可能正在运行也肯能没有运行,这取决于操作系统给线程提供运行的时间。
    • Blocked:阻塞状态。表示线程被锁阻塞,它暂时不活动。
    • Waiting:等待状态。线程暂时不活动,并且不运行任何代码,这消耗最少资源,直到线程调度器重新激活它。
    • Timed waiting:超时等待状态。和等待状态不同的是,它是可以在指定的时间自行返回的。
    • Terminated:终止状态。表示当前线程已经执行完毕。导致线程终止有两种情况:第一种就是run方法执行完毕正常退出;第二种就是因为一个没有捕获的异常而终止了run方法,导致线程进入终止状态。

    线程的简单应用

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

    • New新创建状态
    Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {         
                //do something...   
        }
    });
    System.out.println(thread.getState());
    

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

    • Runnable可运行状态
    Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {         
                
        }
    });
    thread.start();
    System.out.println(thread.getState());
    

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

    • Blocked阻塞状态

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

    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状态。

    • Waiting等待状态

    线程暂时不活动,并且不运行任何代码,调用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 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)方法,看这三个线程的状态。

    • TERMINATED终止状态
    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种状态,下面用一张图来总结


    线程状态

    相关文章

      网友评论

          本文标题:Java之Thread浅谈

          本文链接:https://www.haomeiwen.com/subject/uulmsftx.html