Java多线程详解(1)实现方式

多线程理解
线程百度百科

线程(英语:thread)是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务。

进程百度百科

进程(Process)是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础。在早期面向进程设计的计算机结构中,进程是程序的基本执行实体;在当代面向线程设计的计算机结构中,进程是线程的容器。程序是指令、数据及其组织形式的描述,进程是程序的实体。

进程和线程区分:

  • 进程有自己独立的地址空间,而线程没有,线程必须依赖于进程而存在。
  • 线程与资源分配无关,它属于某一个进程,并与进程内的其他线程一起共享进程的资源。
  • 进程是程序在某个数据集合上的一次运行活动;线程是进程中的一个执行路径。

单一线程(上面左图)只有主线程一条执行路径,多线程(上面右图)是多条执行路径,主线程和子线程并行交替执行

创建多线程的三种方式

  1. 继承Thread类【重点】
  • 自定义线程类继承Thread类
  • 重写run()方法,编写线程执行体
  • 创建线程对象,调用start()方法启动线程
//自定义线程类继承Thread类
public class TestThread extends Thread{
	
	//重写run()方法,编写线程执行体
	@Override
    public void run(){
        for (int i = 0;i < 10;i++){
            System.out.println("run方法执行");
        }
    }

    public static void main(String[] args) {
        //main线程是主线程

        //创建一个线程对象
        TestThread testThread = new TestThread();

        //调用start()方法开启子线程
        testThread.start();

        for (int i=0;i<200;i++){
            System.out.println("主线程执行");
        }
    }

}

运行结果(并行交替执行)

主线程执行
run方法执行
run方法执行
run方法执行
run方法执行
run方法执行
run方法执行
run方法执行
run方法执行
run方法执行
run方法执行
主线程执行
主线程执行
主线程执行

注意:线程开启不一定立即执行,由CPU调度执行

//特别注意如果创建的线程对象调用的不是start(),而是run(),并不是多线程
testThread.run();

运行结果(执行完run方法才回到main方法继续执行下去)

run方法执行
run方法执行
run方法执行
run方法执行
run方法执行
run方法执行
run方法执行
run方法执行
run方法执行
run方法执行
主线程执行

  1. 实现Runnable接口【重点】
  • 自定义MyRunnable类实现Runnable接口
  • 重写run()方法,编写线程执行体
  • 创建线程对象,调用start()方法启动线程
Thread类也是实现了Runnable接口,尽量面向接口编程
public class TestThread2  implements Runnable {

    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            System.out.println("run方法执行");
        }
    }

    public static void main(String[] args) {
        //main线程是主线程
        
        TestThread2 testThread2 = new TestThread2();
		//new Thread(testThread2).start()简化下面两行代码
        //创建一个线程代理对象(静态代理),把自定义类的实列化对象放Thread构造器中(传入目标对象)
        Thread thread = new Thread(testThread2);
        //代理对象调用start()方法开启线程
        thread.start();

        for (int i = 0; i < 200; i++) {
            System.out.println("主线程执行");
        }
    }

}

运行结果(并行交替执行)

主线程执行
run方法执行
run方法执行
run方法执行
run方法执行
run方法执行
run方法执行
主线程执行
主线程执行
run方法执行
run方法执行
run方法执行
主线程执行

第二种方式避免了JAVA单继承局限性,灵活方便,方便同一个对象被多个线程使用(推荐使用)

//多个线程同时操作一个对象(买车票案例)
public class TestThread3 implements Runnable{

    //操作的对象
    private int ticketNumbers = 10;

    @Override
    public void run(){
        while(true){
            if(ticketNumbers<=0){
                break;
            }
            //Thread.currentThread().getName()获取线程名字
            System.out.println(Thread.currentThread().getName()+"-->拿到了第"+ticketNumbers--+"票");
        }
    }

    public static void main(String[] args) {
    	//创建目标对象
        TestThread3 testThread3 = new TestThread3();

        //这里可以理解为run方法为事件,三个人(代理对象)同时执行就是多事件(事件不一样,因为人都不一样了)的同时执行,就是对多线程的通俗理解
        new Thread(testThread3,"小红").start();
        new Thread(testThread3,"小明").start();
        new Thread(testThread3,"小亮").start();
    }
}

继承Thread类也可以实现处理同一个共享资源,有兴趣的可以看看这个案例代码

  1. 实现Callable接口【了解,因为我也不太会了】
  • 自定义MyCallable类实现Callable接口
  • 重写call()方法,编写线程执行体(与上面两种方式不同的是call有返回值,需要抛出异常)
  • 创建目标对象
  • 创建执行服务
  • 提交执行
  • 获取结果
  • 关闭服务
public class TestThread4 implements Callable<Boolean> {
    //操作的对象
    private int ticketNumbers = 10;

    @Override
    public Boolean call(){
        while(true){
            if(ticketNumbers<=0){
                break;
            }
            //Thread.currentThread().getName()获取线程名字
            System.out.println(Thread.currentThread().getName()+"-->拿到了第"+ticketNumbers--+"票");
        }
        return true;
    }

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        TestThread4 t1 = new TestThread4();
        TestThread4 t2 = new TestThread4();
        TestThread4 t3 = new TestThread4();
        //创建执行服务
        ExecutorService executorService = Executors.newFixedThreadPool(3);
        //提交执行
        Future<Boolean> r1 = executorService.submit(t1);
        Future<Boolean> r2 = executorService.submit(t2);
        Future<Boolean> r3 = executorService.submit(t3);
        //获取结果
        boolean rs1 = r1.get();
        boolean rs2 = r2.get();
        boolean rs3 = r3.get();
        //关闭服务
        executorService.shutdown();
    }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值