总结一下java中的线程Thread

今天主要是跟大家一起复习一下java当中的线程,同时对于自己来说也是一种巩固。

废话不多说了,立马进入Thread豪华之旅:

一、主要方法:

Start:启动一个线程(线程创建就不用罗嗦了吧,可以通过Thread和Runnable来初始化一个线程对象);

Sleep:将线程睡眠停滞一段时间,单位是毫秒(不释放同步锁,也就是说,睡眠完毕后会继续往下执行);

Wait:将线程设为等待状态,通过Object.wait来调用(释放同步锁,允许其他线程获得锁);

Join:让某个线程执行完毕后才返回(当前线程进入阻塞状态,知道调用join方法的线程执行完毕),可以参考博文:

http://www.blogjava.net/jnbzwm/articles/330549.html;

Interrupt: 中断某个线程(可以使处于sleep/wait/join状态的线程恢复过来),可以参考博文:http://hi.baidu.com/%D6%D0%B9%A4%D0%A1%D0%DC/blog/item/ba854f02c1181c693912bba8.html;

Notify/notifyAll: 唤醒处于wait状态的线程;

Yield: 出让线程的运行权利,让其他线程获得执行机会;

setDaemon: 设置线程为守护线程;

二、状态变迁:

                      

总结一下java中的线程Thread_第1张图片

三、常用方法深度解析:

Sleep: 有时候我们在开发中需要让某个即将运行或者正在运行的thread休息一段时间(比如当前正在进行文件流的读取操作,当我们调用一个对文件记录写入数据库的线程时,此时文件还未读完或者cpu还很高,就可以让这个线程先睡个觉,呆会让它尽情去执行),调用方法非常简单:Thread.sleep(2000);这就是让线程睡2秒钟的觉,睡觉完后它会继续往下走;

 

Wait: 在生产者/消费者模型中wait就表现得淋漓尽致,注意一点:wait() 必须在synchronized 函数或者代码块里面;执行wait后,当前线程处于等待阻塞状态,需要通过notify/notifyall来唤醒,唤醒后之前处于wait状态的线程不会立即执行,而是需要重新竞争同步锁,只有获取到锁后才会进入到运行等待队列中;它跟sleep的区别在于:

  1. 调用者不同,sleep是通过Thread.sleep调用的,而wait是通过Object.wait调用;
  2. 效果不同,sleep只是暂停,并不交还锁对象,而wait是放弃锁对象;
  3. 使用位置不同,sleep可以在任意地方调用,而wait只能在synchronized或者代码块中调用;

 

setDaemon: 通过一个例子可以清晰地看出该方法的效果:

    

public class TestThread extends Thread {   
       public void run(){   
        for(int i = 1; i <= 100; i++){   
            try{   
                Thread.sleep(100);   
                   
            } catch (InterruptedException ex){   
                ex.printStackTrace();   
            }   
            System.out.println(i);   
        }   
    }   
    public static void main(String [] args){   
        TestThread test = new TestThread();   
        // 如果不设置daemon,那么线程将输出100后才结束   
        test.setDaemon(true);   
        test.start();   
        System.out.println("isDaemon = " + test.isDaemon());   
        try {   
            System.in.read(); // 接受输入,使程序在此停顿,一旦接收到用户输入,main线程结束,守护线程自动结束   
        } catch (IOException ex) {   
            ex.printStackTrace();   
        }   
    }   
} 

通过这个实例可以看出:守护线程的优先级是较低的(相对于一般的用户线程(默认就是setDaemon(false))),当main主线程结束后,守护线程不管有没有运行完毕都立马结束,所以它的生命周期是跟main绑定在一起的,而一般的线程它跟main之间是并行的关系,即使main结束了,用户线程还是会继续运行;

四、实际开发中运用:

实际开发中,我很少直接调用new Thread(XXX).start来执行一个线程程序,除非这个线程是比较简单的,比如只是对数据库中某张表进行扫描;但是当我们需要去进行复杂处理的时候就需要用到线程池了,目前线程池也有一些现成的框架和工具,大家有兴趣的话可以去网上搜罗一下,我用的比较多的是java.util.concurrent包中的Executors类,通过它可以对线程队列中的线程进行调度管理,算是比较方便和好用的了,下面我就简单说说它的具体用法:

  1. 首先可以定义一个总的线程池管理类:(其中getExecutorService方法可以获取一个最基本的线程调度对象;而getScheduledThreadPoolExecutor方法可以获取一个进行定时执行的线程调度对象)

        

 public class ThreadService {

        private ScheduledExecutorService executorService = null;

        private ScheduledThreadPoolExecutor scheduledThreadPoolExecutor =null;

    public ThreadService(){

       int cpu = Runtime.getRuntime().availableProcessors();              

       int corePoolSize = 2*cpu + 1;

       if (executorService == null){

           executorService = Executors.newScheduledThreadPool(corePoolSize);        

       }

       if(scheduledThreadPoolExecutor == null){

           scheduledThreadPoolExecutor = new ScheduledThreadPoolExecutor(corePoolSize);

       }

    }

    public ScheduledExecutorService getExecutorService() {

       return executorService;

    }  

    public ScheduledThreadPoolExecutor getScheduledThreadPoolExecutor(){

       return scheduledThreadPoolExecutor;

    }

}
Public class  TestThread implements Runnable{

   Private String name;

Public void init(String name){

   //该方法不是必须的,它可以传递一些参数

    this.name = name;

}

   Public void run(){

    //在这里进行具体的任务操作

    Sysout(name);

}

}

       调用线程:

ThreadService ser = new ThreadService();

TestThread test = new Thread(new TestThread());

test.init(“我是江上明月”);

ser. getExecutorService().execute(test);


这样就可以将一个线程放入到线程池中了,当然还可以继续放入多个线程,放完之后我们就不用操心了,线程池有自己的调度程序去运行各个线程任务。

你可能感兴趣的:(java,thread)