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实现线程内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • SpringCloud整合Consul的实现

    SpringCloud整合Consul的实现

    这篇文章主要介绍了SpringCloud整合Consul的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-01-01
  • 详解使用Spring AOP和自定义注解进行参数检查

    详解使用Spring AOP和自定义注解进行参数检查

    本篇文章主要介绍了详解使用Spring AOP和自定义注解进行参数检查,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-04-04
  • springboot配置内存数据库H2教程详解

    springboot配置内存数据库H2教程详解

    这篇文章主要介绍了springboot配置内存数据库H2的详细教程,需要的朋友可以参考下
    2017-07-07
  • java泛型的局限探究及知识点总结

    java泛型的局限探究及知识点总结

    在本篇内容里小编给大家分享的是一篇关于java泛型的局限探究及知识点总结内容,有需要的朋友们可以跟着学习参考下。
    2021-07-07
  • SpringBoot集成ActiveMQ的实战全过程

    SpringBoot集成ActiveMQ的实战全过程

    消息队列中间件是分布式系统中重要的组件,主要解决应用耦合、异步消息、流量削锋等问题,实现高性能、高可用、可伸缩和最终一致性架构,是大型分布式系统不可缺少的中间件,这篇文章主要给大家介绍了关于SpringBoot集成ActiveMQ的相关资料,需要的朋友可以参考下
    2021-11-11
  • MybatisPlus中如何调用Oracle存储过程

    MybatisPlus中如何调用Oracle存储过程

    这篇文章主要介绍了MybatisPlus中如何调用Oracle存储过程的问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-05-05
  • Java List的remove()方法踩坑

    Java List的remove()方法踩坑

    Java的List在删除元素时,一般会用list.remove(o)/remove(i)方法。在使用时,容易触碰陷阱,本文就来介绍一下容易踩的坑,感兴趣的可以了解一下
    2021-10-10
  • 解决在SpringBoot中使用@Value取不到值的问题

    解决在SpringBoot中使用@Value取不到值的问题

    这篇文章主要给大家分享解决在SpringBoot中使用@Value取不到值的问题,文中有详细的解决代码供大家参考,具有一定的参考价值,需要的朋友可以参考下
    2023-09-09
  • 浅析Java 反射机制的用途和缺点

    浅析Java 反射机制的用途和缺点

    这篇文章给大家分析了Java 反射机制的用途和缺点以及相关知识点内容,有兴趣的朋友可以参考学习下。
    2018-07-07
  • Mybatis-plus中的@EnumValue注解使用详解

    Mybatis-plus中的@EnumValue注解使用详解

    这篇文章主要介绍了Mybatis-plus中的@EnumValue注解使用详解,在PO类中,如果我们直接使用枚举类型去映射数据库的对应字段保存时,往往就会因为类型不匹配导致映射失败,Mybatis-plus提供了一种解决办法,就是使用@EnumValue注解,需要的朋友可以参考下
    2024-02-02

最新评论