java高并发编程(多线程详解)-多线程基础

什么是线程

线程(英语:thread)是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位

创建线程的四种方式

1. 继承Thread类创建线程

使用:

  1. 继承Thread类,然后实现其run()方法。
  2. 通过new的方式调用start()方法。

特点:继承,继承此类就不能在继承其他类,而实现Runnable接口则可以避免这种缺陷。

示例代码如下:

class MyThread extends Thread {
    @Override
    public void run() {
        System.out.println("继承Thread类的创建方式");
    }
}


public class Test {
    public static void main(String args[]) {
        //启动继承Thread类创建的线程对象
        MyThread t1 = new MyThread();
        t1.start();
    }

2. 实现Runnable接口创建线程

使用:

  1. 实现Runnable 中的run()方法。
  2. 将Runnable接口的子类实体传入thread构造方法中,通过thread.start()进行调用。

特点:

  1. 接口实现的方式进行使用,更加的适用。同时Runnable内部的代码可以被多个线程(Thread实例)共享,适用于多个线程处理同一资源的情况。
  2. 所有接口创建方式都会使用到Runnable,Thread类(Thread 实现了Runnable接口),方式三中的Future也实现了Runnable的接口。
    注:因为所有的线程创建都来源于Runnable接口,如果说线程的创建方式只有一种,那么这种方式就是是Runnable。

特点:继承,继承此类就不能在继承其他类,而实现Runnable接口则可以避免这种缺陷。


class MyRunnable implements Runnable {
    @Override
    public void run() {
        System.out.println("实现Runnable接口");
    }

public class Test {
    public static void main(String args[]) {
        //启动实现Rinnable接口创建的线程对象
        Thread t2 = new Thread(new MyRunnable());
        t2.start();
    }

3. 使用Callable和FutureTask创建线程

java5开始,提供了Callable接口,是Runable接口的增强版。同样用Call()方法作为线程的执行体,增强了之前的run()方法。因为call方法可以有返回值,也可以声明抛出异常。

特点与简单说明
Callable

是一个接口和Runnable类似,使用者需要实现call()方法,在实现call方法时可以返回一个值给调用方。

FutureTask

该类是为创建Callable线程而诞生的,用于管理和创建Callable方式创建的线程,Callable能返回值也是因为这个FutureTask的内部管理和标记二实现的。
FutureTask 实现了Future和Runable接口,起作用:

  • Futurn:用于管理标记其状态以及获取返回值(get()方法)。
  • Runable:用于创建线程。(Callable接口不具备创建线程的能力)
代码示例
  1. 实现且定义Callable子类。
  2. 通过FutureTask进行调用,创建,监督线程。
import java.util.concurrent.Callable;
//Callable<String> -》 声明返回类型String
public class TaskWithResult implements Callable<String> {
    private int id;
    public TaskWithResult(int id) {
        this.id=id;
    }
    
    @Override
    public String call() throws Exception {
        return "Callable return Information: "+id;
    }
}


//Runnable是执行工作的独立任务,但是它不返回任何值。在Java SE5中引入的Callable是一种具有类型参数的泛型,它的类型参数表的是从方法call()中返回的值,并且必须使用ExecutorServices.submit()方法调用它,下面是一个简单示例。

import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.FutureTask;

public class CallableTest {
    public static native void sleep(long millis) throws InterruptedException;

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        System.out.println("使用方式一");
//        //通过借助FutureTask来 调用 运行 获取线程返回数据
//        //1.创建FutureTask并且传入一个callable线程
        FutureTask futureTask = new  FutureTask(new TaskWithResult(66));
//        //2.运行run方法
        futureTask.run();//运行
        System.out.println(futureTask.isCancelled());//是否被取消
        System.out.println(futureTask.isDone());//是否已经结束
//        //3.获取并打印返回值
        System.out.println(futureTask.get());
    }
}

//第二种方式:通过Excutors创建线程
 public static void main(String[] args) throws ExecutionException, InterruptedException {System.out.println("使用方式二");
        //使用Executors来运行callable线程并获取返回结果
        //1.获取ExecutorService对象(就是一个线程池)
        ExecutorService exec=Executors.newCachedThreadPool();
        //2.创建线程并且提交(submit理解为 run() ),获取Future(Future 存储了线程的状态和结果值)
        for(int i=0;i<5;i++) {
            Future<String> submit = exec.submit(new TaskWithResult(i));
            //线程睡眠10毫秒
            Thread.sleep(10);
            // 10毫秒后判断线程是否运行完成,并打印结果
            if(submit.isDone()){System.out.println(submit.get());}
        }

4. 使用线程池框架创建线程的多种方式

Executors

java中提供了一个静态工厂方法来创建不同的线程池: Executors

  1. 通过Executors创建无返回值的线程:
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
 
public class CreateThreadByExecutor {
	public static void main(String[] args) {
		ExecutorService executorService = Executors.newFixedThreadPool(5);
		executorService.execute(()-> System.out.println(Thread.currentThread().getName()));
		executorService.execute(()-> System.out.println(Thread.currentThread().getName()));
		
		executorService.shutdown();
	}
}
  1. 通过Executors创建有返回值的线程:
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
 
public class CreateThreadByExecutors2 {
	public static void main(String[] args) throws InterruptedException, ExecutionException {
		ExecutorService executorService = Executors.newFixedThreadPool(5);
		Future<String> future1 = executorService.submit(() -> {
			return Thread.currentThread().getName();
		});
		Future<String> future2 = executorService.submit(() -> {
			return Thread.currentThread().getName();
		});
		System.out.println(future1.get());
		System.out.println(future2.get());
		
		executorService.shutdown();
	}
}
TThreadPoolExecutors

线程池这块东西不少我先写到这里。这得注意的是excutor创建线程的方式并不可取。原因如下
在这里插入图片描述
具体待定。。。

线程的生命周期

Runable接口的引入以及策略模式

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值