Java:多线程,分别用Thread、Runnable、Callable实现线程

并发性(concurrency)和并行性(parallel)是两个概念,并行是指在同一时刻,有多条指令在多个处理器上同时执行;并发指在同一时刻只能有一条指令执行,但多个进程指令被快速轮换执行,使得宏观上具有多个进程同时执行的效果。

多线程编程优点:

  1. 进程之间不能共享内存,但线程之间共享内存非常容易。
  2. 系统创建线程所分配的资源相对创建进程而言,代价非常小。

Java中实现线程的方式目前有三种:

一:继承Thread类创建线程类

package com.clzhang.sample.thread;

// 通过继承Thread类来创建线程类
public class ThreadByExtends extends Thread {
    private int i;

    @Override
    public void run() {
        // 当线程类继承Thread类时,直接使用this即可获取当前线程句柄。
        // 因此可以直接调用getName()方法返回当前线程的名称。
        System.out.println("当前线程名称是:" + getName());

        for (; i < 5; i++) {
            System.out.println(getName() + ":" + i);
            try {
                // 保证让别的线程也有执行的机会
                Thread.sleep(10);
            } catch (InterruptedException e) {
            }
        }
    }

    public static void main(String[] args) {
        // 静态方法没有this,只能通过Thread.currentThread获取当前线程句柄
        System.out.println(Thread.currentThread().getName());
        
        // 创建、并启动第一条线程
        new ThreadByExtends().start();
        // 创建、并启动第二条线程
        new ThreadByExtends().start();
    }
}

输出:

main
当前线程名称是:Thread-0
Thread-0:0
当前线程名称是:Thread-1
Thread-1:0
Thread-0:1
Thread-1:1
Thread-1:2
Thread-0:2
Thread-1:3
Thread-0:3
Thread-0:4
Thread-1:4

二:实现Runnable接口创建线程类

package com.clzhang.sample.thread;

/**
 * 通过实现Runnable接口来创建线程类
 * 1.Runnable非常适合多个相同线程来处理同一份资源的情况
 * 2.Runnable可以避免由于Java的单继承机制带来的局限
 * 3.如果想获取当前线程句柄,只能用Thread.currentThread()方法
 */
public class ThreadByRunnable implements Runnable {
    private int i;

    @Override
    public void run() {
        System.out.println("当前线程名称是:" + Thread.currentThread().getName());

        for (; i < 5; i++) {
            System.out.println(Thread.currentThread().getName() + ":" + i);

            try {
                // 因为sleep是静态方法,所以不需要通过Thread.currentThread()方法获取当前线程句柄
                Thread.sleep(10);
            } catch (InterruptedException e) {
            }
        }
    }

    public static void main(String[] args) {
        ThreadByRunnable st = new ThreadByRunnable();
        new Thread(st, "新线程1").start();
        new Thread(st, "新线程2").start();
    }
}

输出:

当前线程名称是:新线程1
当前线程名称是:新线程2
新线程2:0
新线程1:0
新线程2:2
新线程1:2
新线程2:3
新线程1:4

三:使用Calable和Future创建具备返回值的线程

package com.clzhang.sample.thread;

import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;

// 实现Callable接口来实现线程
public class ThreadByCallable implements Callable<Integer> {
    
    @Override
    public Integer call() {
        System.out.println("当前线程名称是:" + Thread.currentThread().getName());

        int i = 0;
        for (; i < 5; i++) {
            System.out.println("循环变量i的值:" + i);
        }
        
        // call()方法有返回值
        return i;
    }

    public static void main(String[] args) {
        ThreadByCallable rt = new ThreadByCallable();

        // 使用FutureTask来包装Callable对象
        FutureTask<Integer> task = new FutureTask<Integer>(rt);
        new Thread(task, "有返回值的线程").start();
        try {
            // 获取线程返回值
            System.out.println("子线程的返回值:" + task.get());
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }
}

输出:

当前线程名称是:有返回值的线程
循环变量i的值:0
循环变量i的值:1
循环变量i的值:2
循环变量i的值:3
循环变量i的值:4
子线程的返回值:5

总结

用Runnable与Callable接口的方式创建多线程的特点:

  1. 线程类只是实现了Runnable接口或Callable接口,还可以继承其它类。
  2. 在这种方式下,多个线程可以共享一个target对象,所以非常适合多个线程来处理同一份资源情况。
  3. 如果需要访问当前线程,需要使用Thread.currentThread方法。
  4. Callable接口与Runnable接口相比,只是Callable接口可以返回值而已。

用Thread类的方式创建多线程的特点:

  1. 因为线程已经继承Thread类,所以不可以再继承其它类。
  2. 如果需要访问当前线程,直接使用this即可。
posted @ 2013-08-14 19:55  那些年的事儿  阅读(9990)  评论(0编辑  收藏  举报