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即可。
上一篇:“全栈2019”Java多线程第十章:Thread.State线程状态详解


下一篇:SRM 588 DIV1