- 继承Thread类创建线程类
(1)需要继承Thread类,创建一个新的线程类;
(2)同时重写run()方法,将需要并发执行的业务代码编写在run()方法中;
代码语言:javascript复制public class CreateDemo {
public static final int MAX_TURN = 5;
public static String getCurThreadName() {
return Thread.currentThread().getName();
}
//线程的编号
static int threadNo = 1;
static class DemoThread extends Thread { //①
public DemoThread() {
super("DemoThread-" threadNo ); //②
}
public void run() { //③
for (int i = 1; i < MAX_TURN; i ) {
Print.cfo(getName() ", 轮次:" i);
}
Print.cfo(getName() " 运行结束.");
}
}
public static void main(String args[]) throws InterruptedException {
Thread thread = null;
//方法一:使用Thread子类创建和启动线程
for (int i = 0; i < 2; i ) {
thread = new DemoThread();
thread.start();
}
Print.cfo(getCurThreadName() " 运行结束.");
}
}
- 实现Runnable接口创建线程目标类
2.1 通过匿名类创建Runnable线程目标类
代码语言:javascript复制public class CreateDemo2 {
public static final int MAX_TURN = 5;
static int threadNo = 1;
public static void main(String args[]) throws InterruptedException {
Thread thread = null;
//使用Runnable的匿名类创建和启动线程
for (int i = 0; i < 2; i ) {
thread = new Thread(new Runnable() { //① 匿名实例
@Override
public void run() { //② 异步执行的业务逻辑
for (int j = 1; j < MAX_TURN; j ) {
Print.cfo(getCurThreadName() ", 轮次:" j);
}
Print.cfo(getCurThreadName() " 运行结束.");
}
}, "RunnableThread" threadNo );
thread.start();
}
Print.cfo(getCurThreadName() " 运行结束.");
}
}
2.2 实现Runnable接口的方式创建线程目标类
代码语言:javascript复制package com.crazymakercircle.multithread.basic.create;
// 省略import
public class SalesDemo{
public static final int MAX_AMOUNT = 5; //商品数量
//商店商品类(销售线程类),一个商品一个销售线程,每个线程异步销售4次
static class StoreGoods extends Thread{
StoreGoods(String name){
super(name);
}
private int goodsAmount = MAX_AMOUNT;
public void run(){
for (int i = 0; i <= MAX_AMOUNT; i ){
if (this.goodsAmount > 0){
Print.cfo(getCurThreadName() " 卖出一件,还剩:"
(--goodsAmount));
sleepMilliSeconds(10);
}
}
Print.cfo(getCurThreadName() " 运行结束.");
}
}
//商场商品类(target销售线程的目标类),一个商品最多销售4次,可以多人销售
static class MallGoods implements Runnable{
//多人销售可能导致数据出错,使用原子数据类型保障数据安全
private AtomicInteger goodsAmount = new AtomicInteger(MAX_AMOUNT);
public void run(){
for (int i = 0; i <= MAX_AMOUNT; i ){
if (this.goodsAmount.get() > 0){
Print.cfo(getCurThreadName() " 卖出一件,还剩:"
(goodsAmount.decrementAndGet()));
sleepMilliSeconds(10);
}
}
Print.cfo(getCurThreadName() " 运行结束.");
}
}
public static void main(String args[]) throws InterruptedException{
Print.hint("商店版本的销售");
for (int i = 1; i <= 2; i ){
Thread thread = null;
thread = new StoreGoods("店员-" i);
thread.start();
}
Thread.sleep(1000);
Print.hint("商场版本的销售");
MallGoods mallGoods = new MallGoods();
for (int i = 1; i <= 2; i ){
Thread thread = null;
thread = new Thread(mallGoods, "商场销售员-" i);
thread.start();
}
Print.cfo(getCurThreadName() " 运行结束.");
}
}
- 使用Callable和FutureTask创建线程
对Future接口的主要方法详细说明如下:
·V get():获取异步任务执行的结果。注意,这个方法的调用是阻塞性的。如果异步任务没有执行完成,异步结果获取线程(调用线程)会一直被阻塞,一直阻塞到异步任务执行完成,其异步结果返回给调用线程。
·V get(Long timeout,TimeUnit unit):设置时限,(调用线程)阻塞性地获取异步任务执行的结果。该方法的调用也是阻塞性的,但是结果获取线程(调用线程)会有一个阻塞时长限制,不会无限制地阻塞和等待,如果其阻塞时间超过设定的timeout时间,该方法将抛出异常,调用线程可捕获此异常。
·boolean isDone():获取异步任务的执行状态。如果任务执行结束,就返回true。
·boolean isCancelled():获取异步任务的取消状态。如果任务完成前被取消,就返回true。
·boolean cancel(boolean mayInterruptRunning):取消异步任务的执行。
FutureTask类和Callable接口的联合使用可以创建能够获取异步执行结果的线程:
(1)创建一个Callable接口的实现类,并实现其call()方法,编写好异步执行的具体逻辑,可以有返回值。
(2)使用Callable实现类的实例构造一个FutureTask实例。
(3)使用FutureTask实例作为Thread构造器的target入参,构造新的Thread线程实例。
(4)调用Thread实例的start()方法启动新线程,启动新线程的run()方法并发执行。其内部的执行过程为:启动Thread实例的run()方法并发执行后,会执行FutureTask实例的run()方法,最终会并发执行Callable实现类的call()方法。
(5)调用FutureTask对象的get()方法阻塞性地获得并发线程的执行结果。
代码语言:javascript复制public class CreateDemo3 {
public static final int MAX_TURN = 5;
public static final int COMPUTE_TIMES = 100000000;
//①创建一个 Callable 接口的实现类
static class ReturnableTask implements Callable<Long> {
//②编写好异步执行的具体逻辑,可以有返回值
public Long call() throws Exception{
long startTime = System.currentTimeMillis();
Print.cfo(getCurThreadName() " 线程运行开始.");
Thread.sleep(1000);
for (int i = 0; i < COMPUTE_TIMES; i ) {
int j = i * 10000;
}
long used = System.currentTimeMillis() - startTime;
Print.cfo(getCurThreadName() " 线程运行结束.");
return used;
}
}
public static void main(String args[]) throws InterruptedException {
ReturnableTask task=new ReturnableTask();//③
FutureTask<Long> futureTask = new FutureTask<Long>(task);//④
Thread thread = new Thread(futureTask, "returnableThread");//⑤
thread.start();//⑥
Thread.sleep(500);
Print.cfo(getCurThreadName() " 让子弹飞一会儿.");
Print.cfo(getCurThreadName() " 做一点自己的事情.");
for (int i = 0; i < COMPUTE_TIMES / 2; i ) {
int j = i * 10000;
}
Print.cfo(getCurThreadName() " 获取并发任务的执行结果.");
try {
Print.cfo(thread.getName() "线程占用时间:"
futureTask.get());//⑦
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
Print.cfo(getCurThreadName() " 运行结束.");
}
}
- 通过线程池创建线程
public class CreateDemo4{
public static final int MAX_TURN = 5;
public static final int COMPUTE_TIMES = 100000000;
//创建一个包含三个线程的线程池
private static ExecutorService pool = Executors.newFixedThreadPool(3);
static class DemoThread implements Runnable{
@Override
public void run(){
for (int j = 1; j < MAX_TURN; j ){
Print.cfo(getCurThreadName() ", 轮次:" j);
sleepMilliSeconds(10);
}
}
}
static class ReturnableTask implements Callable<Long>{
//返回并发执行的时间
public Long call() throws Exception{
long startTime = System.currentTimeMillis();
Print.cfo(getCurThreadName() " 线程运行开始.");
for (int j = 1; j < MAX_TURN; j ){
Print.cfo(getCurThreadName() ", 轮次:" j);
sleepMilliSeconds(10);
}
long used = System.currentTimeMillis() - startTime;
Print.cfo(getCurThreadName() " 线程运行结束.");
return used;
}
}
public static void main(String[] args) {
pool.execute(new DemoThread()); //执行线程实例,无返回
pool.execute(new Runnable(){
@Override
public void run(){
for (int j = 1; j < MAX_TURN; j ){
Print.cfo(getCurThreadName() ", 轮次:" j);
sleepMilliSeconds(10);
}
}
});
//提交Callable 执行目标实例,有返回
Future future = pool.submit(new ReturnableTask());
Long result = (Long) future.get();
Print.cfo("异步任务的执行结果为:" result);
sleepSeconds(Integer.MAX_VALUE);
}
}