Java线程基本概念及操作

来源:互联网 发布:校花级别的多漂亮知乎 编辑:程序博客网 时间:2024/05/21 11:22
进程和线程
        进程是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础。线程可以理解为轻量级进程,是程序执行的最小单位。一个进程可以包含一个或者多个线程。

        线程的生命周期如下所示:


新建线程
        方式一:继承Thread类,然后重写里面的run()方法。然后new一个对象,调用start()方法。

Thread t1 = new Thread(){    @Override    public void run(){        System.out.println("Hello world!");    }};t1.start();
        方式二:MyThread实现Runnable接口,然后将MyThread对象作为Thread的构造器入参,创建Thread对象,然后调用start()方法。

Thread t1 = new Thread(new Runnable(){    @Override    public void run(){        System.out.println("Hello Runnable!");    }});t1.start();
终止线程
        通常来说,当我们启动一个线程后,都会让线程运行完成之后自动结束。可以通过Thread.stop()方法暴力终止线程,但是强烈不建议这样用。因为这样会造成程序的不可预测性,从而导致数据的不一致,而且不可恢复。
线程中断
        线程中断是一种重要的线程协作机制。线程中断并不会使线程立即退出,而是给线程发送一个通知,告诉目标线程你可以退出了。其中主要包含以下3个API:

void Thread.interrupt();//中断线程boolean Thread.isInterrupted;//判断是否被中断static boolean Thread.interrupted();//判断是否被中断,并清除当前中断状态
        当通知线程中断时,线程本身需要对中断做处理,否则对于线程的执行没有任何影响。
 public static void main(String[] args) throws InterruptedException {Thread t1 = new Thread() {@Overridepublic void run() {while (true) {if(Thread.currentThread().isInterrupted()) {System.out.println("Interruted!");break;}try {Thread.sleep(2000);} catch (Exception e) {System.out.println("Interrupted when sleep");//设置中断状态Thread.currentThread().interrupt();}Thread.yield();}}};t1.setName("hugege");t1.start();Thread.sleep(2000);t1.interrupt();System.out.println("main end");}
等待和通知
        说到线程的等待和通知,对应的基础的两个方法就是wait()、notify()方法。这两个方法并不在Thread当中,而是在Object中。当一个线程调用了object.wait(),那么它就会进入到object对象的等待队列。当object.notify()方法被调用时,就会从这个等待队列中随机选一个线程进行唤醒操作。并且这个过程是完全随机的。
        object还有一个notifyAll()方法,这个方法是唤醒所有的线程,然后让这些线程去竞争执行,获得监视器对象的才可以继续往下执行。这里面需要注意的是不论是wait()还是notify(),执行前都需要获取到当前对象的监视器,也就是获得当前对象的锁。下面给出一个demo:
/** * wait()和notify()使用 *  */public class SimpleWN {static final Object object = new Object();public static class T1 extends Thread {@Overridepublic void run() {synchronized (object) {System.out.println(System.currentTimeMillis()+":T1 start!");try {System.out.println(System.currentTimeMillis()+"T1: wait for object ");object.wait();} catch (Exception e) {e.printStackTrace();}System.out.println(System.currentTimeMillis()+":T1 end!");}}}public static class T2 extends Thread {@Overridepublic void run() {synchronized (object) {System.out.println(System.currentTimeMillis()+":T2 start! notify one thread");object.notify();System.out.println(System.currentTimeMillis()+"T2: end! ");try {Thread.sleep(2000);} catch (Exception e) {}}}}public static void main(String[] args) {Thread t1 = new T1();Thread t2 = new T2();t1.start();t2.start();}}
        注意:Object.wait()和Thread.sleep()都可以让线程等待一段时间,Object.wait()是释放锁的,而Thread.sleep()是不释放锁的。
挂起和继续执行
        这里面说线程挂起和继续执行分别指的是:suspend()和resume()方法。这里面挂起操作,是不释放锁资源的。查看JDK的文档会发现,这两个API已经被标记为过期了。所以在这里就不详细的介绍了。
等待线程结束和谦让
        等待线程结束调用的方法是Thread.join(),JDK中提供了两个join方法:
final void join() throws InterruptedException;final synchronized void join(long millis) throws InterruptedException;
        如调用了t1.join(),则当前线程会无限等待t1线程,直到t1执行完成。第二个方法则增加了一个超时时间,超过了时间之后,则继续往下执行。其中t1.join()可以理解为,让t1加入到当前线程的串行执行。附demo如下:
public class JoinMain {public volatile static int i = 0;public static class AddThread extends Thread {@Overridepublic void run() {for(i = 0; i < 100000000; i++);}}public static void main(String[] args) throws InterruptedException {AddThread at = new AddThread();at.start();at.join();System.out.println(i);}}
        注意:t1.join()方法的本质是让主线程wait()在 t1 的对象实例上,当t1线程执行完成之后,会调用notifyAll(),从而唤醒主线程。所以在这里不要随意调用Thread.wait()和notify()方法,有可能扰乱join等方法的执行。
        还有一个方法是Thread.yield(),这个方法是静态方法。Thread.yield()表示让当前线程让出CPU,然后再共同竞争CPU资源。这样只会增加别的线程执行的机会,而并不是当前线程一定不执行。

链接:http://moguhu.com/article/detail?articleId=23

原创粉丝点击