有关线程的相关知识(上)

版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://glhcode.blog.csdn.net/article/details/70215452

转载请标明出处:
http://blog.csdn.net/hai_qing_xu_kong/article/details/70215452
本文出自:【顾林海的博客】

前言

一系列任务的同时运行称之为并发,可以认为是多个任务交替执行,并且多个任务之间有可能还是串行的,与并发相关的另一个概念是并行,并行是真正意义上的“同时执行”。

线程的两种创建方式

我们在Java中创建线程可以通过以下两种方式来创建:

  1. 继承Thread类,并且覆盖run()方法。
  2. 创建一个实现Runnable接口的类,使用带参数的Thread构造器来创建Thread对象。

接下来看看以下程序:

public class MyThread extends Thread{

    private int i;

    public MyThread(int i){
        this.i=i;
    }

    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName()+" : "+i);
    }

}

创建了一个继承Thread类的MyThread子类,内部声明了一个名为i的私有int属性,通过构造器来初始化i的值,接着重写run方法,这个方法用来执行我们创建的线程的指令,在run()方法中输出当前线程名和i的值。下面是主类:

public class Client {

    public static void main(String[] args) {
        MyThread thread;
        for(int i=0;i<10;i++){
            thread=new MyThread(i);
            thread.setName("Thread "+i);
            thread.start();
        }
    }

}

我们在主类中通过for循环创建了十个MyThread对象,并给这十个Thread对象设置名字。看看输出结果吧:

Thread 0 : 0
Thread 4 : 4
Thread 3 : 3
Thread 5 : 5
Thread 6 : 6
Thread 2 : 2
Thread 1 : 1
Thread 7 : 7
Thread 8 : 8
Thread 9 : 9

从输出结果来看,代码的运行结果与代码执行顺序或调用顺序是无关的。线程是一个子任务, CPU以不确定的方式,或者说是以随机时间来调用线程的run方法,所以会出现运行结果的顺序与执行顺序不一致的问题。

使用第二种方式实现Runnable接口来实现上面的代码:

public class MyRunnable implements Runnable{

    private int i;

    public MyRunnable(int i){
        this.i=i;
    }

    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName()+" : "+i);
    }

}
public class Client {

    public static void main(String[] args) {
        for(int i=0;i<10;i++){
            MyRunnable runable=new MyRunnable(i);
            Thread thread=new Thread(runable);
            thread.setName("Thread "+i);
            thread.start();
        }
    }

}

最后运行的结果与上面的一样,有可能输出顺序不同。

当然,我们在创建线程时也可以通过Thread类保存的一些属性来标示线程,比如通过getId()方法来获取线程的唯一标识符、通过getName()方法获取线程的名字、以及通过getPriority()方法获取线程的优先级。线程的优先级从1到10,其中1是最低优先级,10是最高优先级。

线程的状态

线程的状态可以通过getState()方法来获取,线程状态有6种:new、runnable、blocked、waiting、time waiting或者terminated。

new状态表示刚刚创建的线程,这种线程还没开始执行。当线程的start()方法被调用时,表示线程开始执行,这时处于runnable状态,如果线程在执行过程中遇到了synchronized同步块,就会进入blocked阻塞状态,这时线程就会暂停执行,直到获得请求的锁。waiting和time waiting都表示等待状态,区别是waiting会进入一个无时间限制的等待,time waiting会进行一个有时间的等待。当线程执行完毕,就会进入terminated状态,表示结束。下面我们用程序来模拟这几种状态。

public class MyRunnable implements Runnable{

    @Override
    public void run() {
        System.out.println("Thread state : "+Thread.currentThread().getState());
    }

}

创建实现Runnable接口的MyRunnable类,并在run方法中,输出当前线程的状态。

public class Client {

    public static void main(String[] args) {
            MyRunnable runable=new MyRunnable();
            Thread thread=new Thread(runable);

            System.out.println("Thread state : "+thread.getState());

            thread.start();
    }

}

我们的主类先是创建MyRunnable对象,并以参数形式创建 Thread对象,随后在start之前获取线程状态。

我们看看输出结果:

Thread state : NEW
Thread state : RUNNABLE

很显然,在线程被构建时,但还没有调用start方法,时处于new状态,随后执行start方法,并在线程执行过程中输出该线程的状态为runnable状态。

下面是waiting和time waiting两种状态。

public class MyRunnable implements Runnable{

    @Override
    public void run() {
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        System.out.println("Thread state : "+Thread.currentThread().getState());
    }

}

我们在run方法中通过Thread类的静态方法sleep睡眠2秒,随后输出该线程状态。

public class Client {

    public static void main(String[] args) {

            MyRunnable runable=new MyRunnable();
            Thread thread=new Thread(runable);
            thread.start();
            try {
                Thread.sleep(1000);
                System.out.println("Thread state : "+thread.getState());
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }


    }

}

在主类中,创建Thread对象,并启动线程,接着睡眠1秒后输出,thread对象的状态,当睡眠一秒后,thread对象还是处于睡眠状态,由此输出结果:

Thread state : TIMED_WAITING
Thread state : RUNNABLE

线程进入等待状态,进入该状态表示当前线程需要等待其他线程做出一些特定动作(通知或中断)。

我们在上面的主类中多加一段代码:

public class Client {

    public static void main(String[] args) {

            MyRunnable runable=new MyRunnable();
            Thread thread=new Thread(runable);
            thread.start();
            try {
                Thread.sleep(1000);
                System.out.println("Thread state : "+thread.getState());
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

            try {
                Thread.sleep(3000);
                System.out.println("Thread state : "+thread.getState());
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

    }

}

在休眠3秒后输出thread对象的状态,这时创建的线程已经执行完毕,我们可以通过运行结果来查看:

Thread state : TIMED_WAITING
Thread state : RUNNABLE
Thread state : TERMINATED

阻塞状态,表示线程阻塞于锁:

public class MyRunnable implements Runnable{

    @Override
    public void run() {
        synchronized (MyRunnable.class) {
            try {
                Thread.sleep(3000);
                System.out.println(Thread.currentThread().getName()+" state : "+Thread.currentThread().getState());
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }

    }

}

创建实现Runnable接口的类,并实现run方法,在run方法中通过synchronized同步这段代码块。

public class Client {

    public static void main(String[] args) {

            MyRunnable runable=new MyRunnable();
            Thread thread1=new Thread(runable,"Thread-1");
            Thread thread2=new Thread(runable,"Thread-2");
            thread1.start();
            thread2.start();

            try {
                thread1.sleep(1000);
                System.out.println(thread2.getName()+" state :"+thread2.getState());
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

    }

}

在主类中创建了两个Thread对象,当两个线程执行start方法后,睡眠1秒,输出thread2的状态,这时,thread1睡眠3秒才会释放锁,因此,thread2因为同步机制被挂起,直到thread1线程离开synchronized同步块(临界区)。运行结果:

Thread-2 state :BLOCKED
Thread-1 state : RUNNABLE
Thread-2 state : RUNNABLE
展开阅读全文

没有更多推荐了,返回首页