java线程实现的三种方式

来源:互联网 发布:鲁能泰山 网络直播 编辑:程序博客网 时间:2024/05/22 05:07
Java中使用Thread代表线程类,所有的线程类都必须是Thread类或者其子类的实例。每个线程的作用就是完成一定的任务,即执行一段程序流。Java中使用线程执行体来表示这段程序流。


Java中线程的实现方式有如下三种:


1.继承Thread类
public class Thread extends Object implements Runnable
定义Thread类的子类,并重写Thread类的run()方法,创建子类对象(即线程对象),调用线程对象的start()方法来启动该线程。

/**
 * @Description:
 * @author WEISANGENG
 * @date 2017年3月3日
 */
public class ThreadDemo extends Thread {


private int i;


/**
* @功能描述: Thread线程的方式
*  
* @date 2017年3月3日
* @author WEISANGENG
*/
@Override
public void run() {
for (; i < 100; i++) {
System.out.println(getName() + " " + i);
}
}


public static void main(String[] args) {
for (int i = 0; i < 100; i++) {
// currentThread是Thread类的静态方法,该方法返回当前正在执行的线程对象
// getName()返回当前线程对象的名字
System.out.println(Thread.currentThread().getName() + " " + i);
if (i == 20) {
// 启动两个线程,但是实际上有三个线程,即main主线程
// 用户启动的多个线程的名字依次为Thread-0、Thread-1、、、、
new ThreadDemo().start();
new ThreadDemo().start();
}
}


}
}


/*注意:该例中第一次出现的变量i是实例变量,而每次创建线程对象时候,Thread-0和Thread-1两个线程对象不能共享实例变量i。
即使用继承Thread方法创建线程对象时,多个线程之间无法共享线程类的实例变量。*/




2.实现Runnable接口
public interface Runnable
定义Runnable接口的实现类,并重写该接口的run()方法,该run()方法同样是该线程的执行体。创建该Runnable实现类的实例,并将此实例作为Thread的target(即构造函数中的参数)来创建Thread对象(该Thread对象才是真正的线程对象,只是该Thread对象负责执行其target的run()方法)。最后调用线程对象的start()方法来启动该线程。

/**
 * @Description: TODO(用一句话描述该文件做什么)
 * @author WEISANGENG
 * @date 2017年3月3日
 */
public class RunnableDemo implements Runnable {


private int i;


@Override
public void run() {
for (; i < 100; i++) {
// 当线程类实现Runnable接口时,只能通过Thread.currentThread()方法获得当前线程
System.out.println(Thread.currentThread().getName() + " " + i);
}
}


public static void main(String[] args) {
for (int i = 0; i < 100; i++) {
System.out.println(Thread.currentThread().getName() + " " + i);
if (i == 20) {
ThreadDemo td = new ThreadDemo();
// 创建两个Thread对象,并且均把Runnable接口实例对象作为target
new Thread(td).start();
new Thread(td).start();
}
}


}


}




3.使用Callable和Future 
Executor是Java线程池的顶级接口
备注:ScheduledExecutorService描述的功能和Timer/TimerTask类似,解决那些需要任务重复执行的问题。这包括延迟时间一次性执行、延迟时间周期性执行以及固定延迟时间周期性执行等。当然了继承ExecutorService的ScheduledExecutorService拥有ExecutorService的全部特性。
Executors是一个类

Executors类提供了若干个静态方法,用于生成不同类型的线程池:

/** 
 * @Description: 启动一个任务,然后等待任务的计算结果,如果等待时间超出预设定的超时时间,则中止任务。
 * @author WEISANGENG   
 * @date 2017年3月3日     
 */
public class ExecutorServiceTest {

public static void main(String[] args) {
System.out.println("Start ...");  
//创建一个可缓存的线程池。如果线程池的大小超过了处理任务所需要的线程,
//那么就会回收部分空闲(60秒不执行任务)的线程,当任务数增加时,此线程池又可以智能的添加新线程来处理任务。
//此线程池不会对线程池大小做限制,线程池大小完全依赖于操作系统(或者说JVM)能够创建的最大线程大小。
        ExecutorService exec = Executors.newCachedThreadPool();
          
        //testTask(exec, 15); // 任务成功结束后等待计算结果,不需要等到15秒  
        testTask(exec, 5); // 只等待5秒,任务还没结束,所以将任务中止  
  
        exec.shutdown();  
        System.out.println("End!");
}
public static void testTask(ExecutorService exec, int timeout) {  
        MyTask task = new MyTask();
        //提交一个返回值的任务用于执行,返回一个表示任务的未决结果的 Future。
        //该 Future 的 get 方法在成功完成时将会返回该任务的结果。
        Future<Map<String, Object>> future = exec.submit(task);
        Map<String, Object> taskResult = null; 
        String failReason = null;  
        try {  
            // 等待计算结果,最长等待timeout秒,timeout秒后中止任务  
            taskResult = future.get(timeout, TimeUnit.SECONDS);  
        } catch (InterruptedException e) {  
            failReason = "主线程在等待计算结果时被中断!";  
        } catch (ExecutionException e) {  
            failReason = "主线程等待计算结果,但计算抛出异常!";  
        } catch (TimeoutException e) {  
            failReason = "主线程等待计算结果超时,因此中断任务线程!";  
        }  
        exec.shutdownNow(); 
        System.out.println("\ntaskResult : " + taskResult);  
        System.out.println("failReason : " + failReason);  
    }  



/**
 * 
 * @Description: 任务器
 * @author WEISANGENG
 * @date 2017年3月3日
 */
class MyTask implements Callable<Map<String, Object>> {  
 
    @Override  
    public Map<String, Object> call() throws Exception {  
        // 总计耗时约10秒  
        for (int i = 0; i < 10; i++) {  
            Thread.sleep(1000); // 睡眠1秒  
            System.out.println("第"+(i+1)+"秒");
        }
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("key", "weisg81");
        return map;  
    }  



0 0
原创粉丝点击