当前位置: 首页 > news >正文

java多线程

java多线程

术语辨析

  1. 任务和线程是不同的,Java中Thread类本身不执行任何操作,它只驱动赋予它的任务,而Runnable才是定义任务的地方.

创建任务的方式有两种

  1. 实现Runnable接口中的run方法.
  • 查看Runnable源码,可以看到只有一个run()方法
   @FunctionalInterface
public interface Runnable {
    /**
     * When an object implementing interface <code>Runnable</code> is used
     * to create a thread, starting the thread causes the object's
     * <code>run</code> method to be called in that separately executing
     * thread.
     * <p>
     * The general contract of the method <code>run</code> is that it may
     * take any action whatsoever.
     *
     * @see     java.lang.Thread#run()
     */
    public abstract void run();
}
  • 使用Runnable,直接继承即可,这样就创建了一个任务.
public class MyRunnable implements Runnable{

    @Override
    public void run() {
        int i=0;
        while(true)
            System.out.println(i++);
    }
    //暗示调度器该线程可以让出资源了
    Thread.yield();
}
  1. Thread中实现run方法;
  • Thread部分源码
/*
 * @see     Runnable
 * @see     Runtime#exit(int)
 * @see     #run()
 * @see     #stop()
 * @since   JDK1.0
 */
public class Thread implements Runnable {
    /* Make sure registerNatives is the first thing <clinit> does. */
    private static native void registerNatives();
    static {
        registerNatives();
    }
  • 可以看到Thread继承了Runnable接口,所以Thread创建任务也是用的run方法
  • 代码可以这样写
class MyThread extends Thread{
    @Override
    public void run() {
        int count=10;
        while(count--!=0)
            System.out.print(count+" ");
    }
}

运行任务

  1. 不要误会,下面的方法并未启动一个线程,而是单纯的调用了实现Runnable接口的MyRunnable的run()方法,所以该任务的运行依旧被分派到该main线程中,不会独立运行在一个新线程里.
public class Main{
    public static void main(String[] args){
        Runnable runnable=new Runnable();
        runnable.run();
    }
}
  1. 调用Thread的start(),Thread中记录了很多线程信息,包括线程名称和优先级等,以MyRunnable的实例作参传入Thread,然后start即可运行.
public static void main(String[] args){

Thread thread=new Thread(new MyRunnable);
thread.start()
}
  • 在调用start()后,子线程不会因为主线程代码执行结束而停止.

3.使用执行器(Executor)管理Thread.

public static void main(String[] args){

    //常见执行器对象
    ExecutorService executorService= Executors.newCachedThreadPool();
    //向执行器中添加任务
    executorService.execute(new MyRunnable());
    //关闭向执行器中添加任务;
    executorService.shutdown();
  • 创建执行器又三种类型可选,分别是newCachedThreadPool,newFixedThreadPool,newSingleThreadPool,区别如下
  1. newCachedThreadPool:系统自动调配线程池中的线程数量,并主动复用已完成的线程资源.
  2. newFixedThreadPool:可以自定义线程池中线程数量;
  3. newSingleThreadPool:单例,线程池中只有一个线程,加载的任务会被排队,任务只能一个个依次完成.

线程的返回值

  • 有些任务执行完后需要返回值,那么创建任务时可以通过实现Callale接口而实现该目的,Callable是一种具有类型参数的泛型,因为返回值是需要定义类型的.
class Task implements Callable<String>{

    @Override
    public String call() throws Exception {
        Thread.currentThread().setPriority(Thread.MAX_PRIORITY);
        TimeUnit.MILLISECONDS.sleep(100);
        return "线程执行啦";
    }
}
  • 然后在main()方法中接受返回值信息,对线程信息的管理可以用Future<String>
public static void main(String[] args){
    ExecutorService executorService=Executors.newCachedThreadPool();
    Future<String> future=executorService.submit(new Callable<String>(){    
        @Override   
        public String call() throws Exception {
        return "执行啦";   
        }
    });
    //判断是否完成
    System.out.println(future.isDone());
    //任务完成后,才会打印词条语句,否则会阻塞.
    System.out.println(future.get());
    //判断是否完成
    System.out.println(future.isDone());
}
----------输出----------
false
执行啦
true
  • 程序运行到get()方法时会阻塞,当运行完后,主程序才会继续向后执行.

程序的优先级

  • 优先级的设置在run方法中
public void run(){

    //例如将优先级设置为10
    Thread.currentThread().setPriority(10)
}
  • 为了方便移植,建议将优先级设置为Thread中的三个常量.

后台线程

  • 设置后台线程语法 thread.setDaemon(true);要在start()之前.
  • 后台线程创建的线程也为后台线程.

相关文章:

  • 喜讯:以太坊“君士坦丁堡”升级,截止目前稳定运转
  • 如何找到 Kafka 集群的吞吐量极限?
  • Atcoder:AGC004F Namori
  • 如何学习JavaEE,项目又该如何做?
  • Spring Cloud构建微服务架构—服务消费(Ribbon)
  • long a = 136;
  • 使用权重正则化较少模型过拟合
  • Angular 响应式表单之下拉框
  • 基于 Babel 的 npm 包最小化设置
  • 洞悉物联网发展1000问之热点技术这么多,物联网的机会在哪里?
  • 另人的评测
  • vue 组件中solt 插槽使用
  • 设计模式(三)Animation中的策略模式
  • 手写springmvc框架
  • 你炒的肉丝为何又柴又老又难吃?
  • 《网管员必读——网络组建》(第2版)电子课件下载
  • 【407天】跃迁之路——程序员高效学习方法论探索系列(实验阶段164-2018.03.19)...
  • HTML5新特性总结
  • JavaScript的使用你知道几种?(上)
  • Mysql数据库的条件查询语句
  • node和express搭建代理服务器(源码)
  • vue2.0开发聊天程序(四) 完整体验一次Vue开发(下)
  • vue-cli在webpack的配置文件探究
  • web标准化(下)
  • Zsh 开发指南(第十四篇 文件读写)
  • 工作踩坑系列——https访问遇到“已阻止载入混合活动内容”
  • 如何学习JavaEE,项目又该如何做?
  • 数据仓库的几种建模方法
  • 思考 CSS 架构
  • 微服务入门【系列视频课程】
  • 译有关态射的一切
  • 因为阿里,他们成了“杭漂”
  • 宾利慕尚创始人典藏版国内首秀,2025年前实现全系车型电动化 | 2019上海车展 ...
  • 交换综合实验一
  • 如何在招聘中考核.NET架构师
  • ​io --- 处理流的核心工具​
  • ​secrets --- 生成管理密码的安全随机数​
  • # 20155222 2016-2017-2 《Java程序设计》第5周学习总结
  • #13 yum、编译安装与sed命令的使用
  • #include
  • #pragma data_seg 共享数据区(转)
  • #QT(一种朴素的计算器实现方法)
  • (delphi11最新学习资料) Object Pascal 学习笔记---第7章第3节(封装和窗体)
  • (附源码)spring boot儿童教育管理系统 毕业设计 281442
  • (紀錄)[ASP.NET MVC][jQuery]-2 純手工打造屬於自己的 jQuery GridView (含完整程式碼下載)...
  • (转)EOS中账户、钱包和密钥的关系
  • (转)关于多人操作数据的处理策略
  • .bashrc在哪里,alias妙用
  • .mat 文件的加载与创建 矩阵变图像? ∈ Matlab 使用笔记
  • .NetCore 如何动态路由
  • .Net下使用 Geb.Video.FFMPEG 操作视频文件
  • /bin/bash^M: bad interpreter: No such file ordirectory
  • ::before和::after 常见的用法
  • [ vulhub漏洞复现篇 ] Celery <4.0 Redis未授权访问+Pickle反序列化利用
  • []T 还是 []*T, 这是一个问题