Java实现线程的四种方式解析

 更新时间:2023年10月18日 09:16:18   作者:喜上编程  
这篇文章主要介绍了Java实现线程的四种方式解析,线程是进程中的一个执行单元,负责当前进程中程序的执行,一个进程中至少有一个线程,一个进程中是可以有多个线程的,这个应用程序也可以称之为多线程程序,需要的朋友可以参考下

概念

进程

进程指正在运行的程序。确切的来说,当一个程序进入内存运行,即变成一个进程,进程是处于运行过程中的程序,并且具有一定独立功能

线程

线程是进程中的一个执行单元,负责当前进程中程序的执行,一个进程中至少有一个线程。一个进程中是可以有多个线程的,这个应用程序也可以称之为多线程程序

程序

程序是含有指令和数据的文件,被存储在磁盘或其他的数据存储设备中,也就是说程序是静态的代码。

主线程

jvm启动后,必然有一个执行路径(线程)从main方法开始的,一直执行到main方法结束,这个线程在java中称之为主线程。

进程调度策略

java主要用的是抢占式调度 进程调度的方式参考进程调度策略

创建线程的方法(四种)

1.匿名代码块

package com.it.threads;
public class Demo2 {
    public static void main(String[] args) {
        new Thread(){
            @Override
            public void run() {
                for (int i = 0; i <1000 ; i++) {
      System.out.println(Thread.currentThread().getName()+"---===>"+i);
                }
            }
        }.start();
        System.out.println("-----------main over--------------");
    }
}

2.继承Thread类

package com.it.threads;

/**
 * 创建线程的步骤: 1 定义一个类继承 Thread。
 * 2 重写 run 方法。
 * 3 创建子类对象,就是创建线程对象。
 * 4 调用 start 方法,开启线程并让线程执行,
 * 同时还会告诉 jvm 去调用 run 方法。
 * @version: $
 */
public class ThreadA extends Thread {
    /**
     * 线程的任务写在run方法中
     */
    @Override
    public void run() {
        for (int i = 0; i < 1000; i++) {
            System.out.println(Thread.currentThread().getName() + "-->" + i);
        }
    }
    public static void main(String[] args) {
        ThreadA threadA = new ThreadA();
        //设置线程的名字
        threadA.setName("得力");
        threadA.setPriority(10);
        //设置线程的优先级
        ThreadA threadA1 = new ThreadA();
        //设置线程的名字
        threadA1.setName("得力1");
        threadA1.setPriority(Thread.MIN_PRIORITY);
        threadA1.start();
        threadA.start();
        System.out.println(threadA.getPriority());
        System.out.println(threadA1.getPriority());
    }
}

3.实现Runnable接口

package com.it.threads;
/**
 * 1、定义类实现 Runnable 接口。
 * 2、覆盖接口中的 run 方法。。
 * 3、创建 Thread 类的对象
 * 4、将 Runnable 接口的子类对象作为参数传递给 Thread 类的构造函数。
 * 5、调用 Thread 类的 start 方法开启线程。
 * @version:     $
 */
public class ThreadB implements  Runnable {
    @Override
    public void run() {
        for (int i = 0; i <1000 ; i++) {
            System.out.println(Thread.currentThread().getName()+"---->"+i);
        }
    }
    public static void main(String[] args) {
        ThreadB threadB = new ThreadB();
        Thread thread1 = new Thread(threadB,"aa");
        Thread thread2 = new Thread(threadB,"bb1");
        //启动线程
        thread1.start();
        thread2.start();
    }
}

4.线程池

线程池,其实就是一个容纳多个线程的容器,其中的线程可以反复使用,省去了频繁创建线程对象的操作,无需反复创建线程而消耗过多资源。 实现线程池分为两种

(1)实现Runnable

创建一个线程

package com.it.threadpool;
//方式一    实现Runnable接口
public class ThreadRunnable implements Runnable {
    @Override
    public void run() {
        for (int i = 0; i <2; i++) {
           System.out.println(Thread.currentThread().getName()+i+"进入电影院");
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName()+i+"离开电影院");
        }
    }
}

创建线程池

package com.it.threadpool;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/*
* 创建线程池对象
创建Runnable接口子类对象
提交Runnable接口子类对象
关闭线程池
* */
public class ThreadRunnablePool {
    public static void main(String[] args) {
        //创建线程池对象 线程个数  Executors:线程池创建工厂类  ExecutorService:线程池类
        ExecutorService executorService = Executors.newFixedThreadPool(5);
        //创建Runnable实例对象
        ThreadRunnable threadRunnable = new ThreadRunnable();
        //从线程池中获取线程对象,然后调用run()
        executorService.submit(threadRunnable);
        executorService.submit(threadRunnable);
        executorService.submit(threadRunnable);
        executorService.shutdown();
    }
}

(2)实现Callable接口

创建线程

package com.it.threadpool;

import java.util.concurrent.Callable;

public class ThreadCallable implements Callable {
    @Override
    public Object call() throws Exception {
        System.out.println("我要一个教练:call");
        Thread.sleep(2000);
        System.out.println("教练来了: " +Thread.currentThread().getName());
        System.out.println("教我游泳,交完后,教练回到了游泳池");
        return null;
    }
}

创建线程池

package com.it.threadpool;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ThreadCallablePool {
    public static void main(String[] args) {
        //创建线程池
        ExecutorService service = Executors.newFixedThreadPool(2);
        //生成Callable对象
        ThreadCallable threadCallable=new ThreadCallable();
        //从线程池中获取线程对象,然后调用run()
        service.submit(threadCallable);
        service.submit(threadCallable);
        service.submit(threadCallable);
        service.shutdown();
    }
}

这两种方式的区别如下:

  • Callable定义的方法是call,而Runnable定义的方法是run。
  • Callable的call方法可以有返回值,而Runnable的run方法不能有返回值,这是核心区别。
  • Callable的call方法可抛出异常,而Runnable的run方法不能抛出异常。

举一个例子说明 创建一个线程用来求和

package com.it.threadpool;
import java.util.concurrent.Callable;
public class ThreadSum implements Callable<Integer> {
    int x;
    int y;
    public ThreadSum(int x, int y) {
        this.x = x;
        this.y = y;
    }
    @Override
    public Integer call() throws Exception {
        return x+y;
    }
}

创建线程池

package com.it.threadpool;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class ThreadSumPool {
    public static void main(String[] args) {
     ExecutorService executorService= Executors.newFixedThreadPool(5);
     //Future用来接收call方法的返回值
        Future future1=executorService.submit(new ThreadSum(200,500));
        Future future2=executorService.submit(new ThreadSum(100,500));
        Future future3= executorService.submit(new ThreadSum(200,600));
        try {
        //get()方法用来获取返回值
            System.out.println(future1.get());
            System.out.println(future2.get());
            System.out.println(future3.get());
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
    }
}

到此这篇关于Java实现线程的四种方式解析的文章就介绍到这了,更多相关Java实现线程内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 一篇文章让你彻底学会Java之exists()方法

    一篇文章让你彻底学会Java之exists()方法

    Java中File.exists()方法用于检查文件或目录是否存在,是文件操作的前置检查工具,这篇文章主要介绍了Java之exists()方法的相关资料,文中通过代码介绍的非常详细,需要的朋友可以参考下
    2025-07-07
  • java中基本数据类型与Object的关系说明

    java中基本数据类型与Object的关系说明

    这篇文章主要介绍了java基本数据类型与Object的关系说明,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-03-03
  • Springboot实现ENC加密的详细流程

    Springboot实现ENC加密的详细流程

    在项目开发过程中,需要配置数据库连接密码、Redis密码、网盘上传的AK/SK等敏感信息,都需要保存在配置文件里,或者配置中心,这些信息如果泄露,还是会造成一定的困扰,下面这篇文章主要给大家介绍了关于Springboot实现ENC加密的详细流程,需要的朋友可以参考下
    2023-06-06
  • Java实现输出数字三角形实例代码

    Java实现输出数字三角形实例代码

    大家好,本篇文章主要讲的是Java实现输出三角形实例代码,感兴趣的同学赶快来看一看吧,对你有帮助的话记得收藏一下,方便下次浏览
    2022-01-01
  • Druid之连接创建及销毁示例详解

    Druid之连接创建及销毁示例详解

    这篇文章主要为大家介绍了Druid之连接创建及销毁示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-02-02
  • springBoot整合rabbitmq测试常用模型小结

    springBoot整合rabbitmq测试常用模型小结

    这篇文章主要介绍了springBoot整合rabbitmq并测试五种常用模型,本文主要针对前五种常用模型,在spirngboot框架的基础上整合rabbitmq并进行测试使用,需要的朋友可以参考下
    2022-01-01
  • springmvc级联属性处理无法转换异常问题解决

    springmvc级联属性处理无法转换异常问题解决

    这篇文章主要介绍了springmvc级联属性处理无法转换异常问题解决,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-12-12
  • SpringBoot配置使Mybatis打印SQL执行时的实际参数值操作

    SpringBoot配置使Mybatis打印SQL执行时的实际参数值操作

    这篇文章主要介绍了SpringBoot配置使Mybatis打印SQL执行时的实际参数值操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-12-12
  • Java函数式编程(八):字符串及方法引用

    Java函数式编程(八):字符串及方法引用

    这篇文章主要介绍了Java函数式编程(八):字符串及方法引用,本文是系列文章的第8篇,其它文章请参阅本文底部的相关文章,需要的朋友可以参考下
    2014-09-09
  • 举例讲解Java设计模式中的对象池模式编程

    举例讲解Java设计模式中的对象池模式编程

    这篇文章主要介绍了Java设计模式中的对象池模式编程示例分享,对象池模式经常在多线程开发时被用到,需要的朋友可以参考下
    2016-02-02

最新评论