java多个线程同时启动的两种方式

1 java多线程 线程的创建和线程中变量的共享 线程的创建方法 java中创建线程的方法可以说只有一个,就是通过new Thread()的方式来创建线程。但是,从使用的角度来看,java中创建线程的方式可以说是有多种的: 1 第一种可以通过继承 Thread 类,重写 Thread 类中的 run() 函数来实现线程逻辑。然后在主类中通过新建一个Thread的实现类来开启线程。 2 实现Runnable接口,重写 run() 方法即可。采用接口的方式来创建线程相对而言更加灵活,毕竟java只支持单继承,继承Thread类就没办法继承自己的类啦。 需要注意 阅读详情

【背景】今天遇到一个并发问题,为了在开发环境复现这个bug,需要让多个线程同时执行到某条语句。

【解决方案】

java1.5的concurrent包下的CyclicBarrier 和 CountDownLatch都能解决这个问题。不得不佩服Doug Lea!

【方法1】使用CyclicBarrier

public class TestCyclicBarrier {
    class Worker implements Runnable{
        CyclicBarrier cyclicBarrier;

        public Worker(CyclicBarrier cyclicBarrier){
            this.cyclicBarrier = cyclicBarrier;
        }

        @Override
        public void run() {
            try {
                cyclicBarrier.await(); // 等待其它线程
                System.out.println(Thread.currentThread().getName() + "启动@" + System.currentTimeMillis());
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (BrokenBarrierException e) {
                e.printStackTrace();
            }
        }
    }

    public void doTest() throws InterruptedException {
        final int N = 5; // 线程数
        CyclicBarrier cyclicBarrier = new CyclicBarrier(N);
        for(int i=0;i<N;i++){
            new Thread(new Worker(cyclicBarrier)).start();
        }
    }

    public static void main(String[] args) throws InterruptedException {
        TestCyclicBarrier testCyclicBarrier = new TestCyclicBarrier();
        testCyclicBarrier.doTest();
    }
}

【方法2】使用CountDownLatch

package thread;

import java.util.concurrent.CountDownLatch;

public class TestCountDownLatch {
    class Worker implements Runnable{
        CountDownLatch countDownLatch;

        Worker(CountDownLatch countDownLatch){
            this.countDownLatch = countDownLatch;
        }

        @Override
        public void run() {
            try {
                countDownLatch.await(); // 等待其它线程
                System.out.println(Thread.currentThread().getName() + "启动@" + System.currentTimeMillis());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public void doTest() throws InterruptedException {
        final int N = 5; // 线程数
        CountDownLatch countDownLatch = new CountDownLatch(N);
        for(int i=0;i<N;i++){
            new Thread(new Worker(countDownLatch)).start();
            countDownLatch.countDown();
        }
    }

    public static void main(String[] args) throws InterruptedException {
        TestCountDownLatch testCountDownLatch = new TestCountDownLatch();
        testCountDownLatch.doTest();
    }
}

这里记录一下下面这种情况:主线程需要等待多个子线程执行完后再执行。

我们先看一下下面的场景:

package com.java4all.mypoint;

import java.util.concurrent.CountDownLatch;

/**
 * Author: yunqing
 * Date: 2018/7/18
 * Description:线程测试
 * 测试点:主线程等待子线程全部执行完后再执行
 */
public class ThreadTest {

    public static void main(String[] args)throws Exception{
        System.out.println("主线程正在执行前:"+Thread.currentThread().getName());
        test3();
        System.out.println("主线程正在执行后:"+Thread.currentThread().getName());
    }

    public static void test3(){
        try {
            for (int i = 1 ;i <= 10;i ++){
                Thread.sleep(1000);
                new Thread(()->{
                    System.out.println("子线程正在执行:"+Thread.currentThread().getName());
                }).start();
            }
        }catch (Exception ex){
            ex.printStackTrace();
        }
    }

}

执行结果为:

主线程正在执行前:main
子线程正在执行:Thread-0
子线程正在执行:Thread-1
子线程正在执行:Thread-2
子线程正在执行:Thread-3
子线程正在执行:Thread-4
子线程正在执行:Thread-5
子线程正在执行:Thread-6
子线程正在执行:Thread-7
子线程正在执行:Thread-8
主线程正在执行后:main
子线程正在执行:Thread-9

可以看到,子线程还没执行完时,主线程进来了。

1.使用CountDownLatch

示例如下,我们初始化一个CountDownLatch,值为10(子线程个数),然后每次一个子线程执行完后执行一下countDown(),代码示例如下:

package com.java4all.mypoint;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

/**
 * Author: yunqing
 * Date: 2018/7/18
 * Description:线程测试
 * 测试点:主线程等待子线程全部执行完后再执行
 */
public class ThreadTest {

    /**初始化CountDownLatch,值为线程数量*/
    private static final CountDownLatch ctl = new CountDownLatch(10);
    
    public static void main(String[] args)throws Exception{
        System.out.println("主线程正在执行前:"+Thread.currentThread().getName());
        test3();
        ctl.await(20, TimeUnit.SECONDS);//最多等待20秒,不管子线程完没完
        System.out.println("主线程正在执行后:"+Thread.currentThread().getName());
    }


    public static void test3(){
        try {
            for (int i = 1 ;i <= 10;i ++){
                Thread.sleep(1000);
                new Thread(()->{
                    System.out.println("子线程正在执行:"+Thread.currentThread().getName());
                }).start();
                ctl.countDown();
            }
        }catch (Exception ex){
            ex.printStackTrace();
        }
    }

}

执行结果为:

主线程正在执行前:main
子线程正在执行:Thread-0
子线程正在执行:Thread-1
子线程正在执行:Thread-2
子线程正在执行:Thread-3
子线程正在执行:Thread-4
子线程正在执行:Thread-5
子线程正在执行:Thread-6
子线程正在执行:Thread-7
子线程正在执行:Thread-8
子线程正在执行:Thread-9
主线程正在执行后:main

或者用java8之前的方式写:

线程类:

package com.java4all.mypoint;

import java.util.concurrent.CountDownLatch;

/**
 * Author: yunqing
 * Date: 2018/7/23
 * Description:
 */
public class MyRunnable implements Runnable{

    public CountDownLatch countDownLatch;

    @Override
    public void run() {
        try {
            Thread.sleep(2000);
            System.out.println("子线程正在执行任务,当前线程为:"+Thread.currentThread().getName());
        }catch (InterruptedException inex){
            inex.printStackTrace();
        }finally {
            countDownLatch.countDown();
        }
    }


    public CountDownLatch getCountDownLatch() {
        return countDownLatch;
    }

    public void setCountDownLatch(CountDownLatch countDownLatch) {
        this.countDownLatch = countDownLatch;
    }
}

测试类:

package com.java4all.mypoint;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

/**
 * Author: yunqing
 * Date: 2018/7/18
 * Description:线程测试
 * 测试点:主线程等待子线程全部执行完后再执行
 */
public class ThreadTest {

    /**初始化CountDownLatch,值为线程数量*/
    private static final CountDownLatch ctl = new CountDownLatch(10);

    public static void main(String[] args)throws Exception{
        System.out.println("主线程正在执行前:"+Thread.currentThread().getName());
        for(int i = 1;i <= 10;i ++){
            MyRunnable runnable = new MyRunnable();
            runnable.setCountDownLatch(ctl);
            Thread thread = new Thread(runnable);

            thread.start();
        }
        ctl.await(20, TimeUnit.SECONDS);//最多等待20秒,不管子线程完没完
        System.out.println("主线程正在执行后:"+Thread.currentThread().getName());
    }

}

结果为:

主线程正在执行前:main
子线程正在执行任务,当前线程为:Thread-1
子线程正在执行任务,当前线程为:Thread-0
子线程正在执行任务,当前线程为:Thread-2
子线程正在执行任务,当前线程为:Thread-3
子线程正在执行任务,当前线程为:Thread-4
子线程正在执行任务,当前线程为:Thread-7
子线程正在执行任务,当前线程为:Thread-6
子线程正在执行任务,当前线程为:Thread-5
子线程正在执行任务,当前线程为:Thread-9
子线程正在执行任务,当前线程为:Thread-8
主线程正在执行后:main

附:
开启一个线程的其他写法:

    /**jdk7匿名内部类的写法*/
    public static void test1(){
        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("aaaa");
            }
        }).start();
    }

    /**
	 * jdk8
	 * Runnable是个函数接口,可以利用jdk8的lambda来简写
     * 函数接口:是指内部只有一个抽象方法的接口
     * */
    public static void test2(){
        new Thread(()->{
            System.out.println("bbb");
        }).start();
    }

 

Python中如何使用ThreadPoolExecutor一次开启多个线程 通过本文的介绍,我们可以了解到是Python中用于实现多线程并发执行的类。通过使用,我们可以方便地创建线程池、提交任务、获取执行结果以及处理异常等。在使用多线程时,我们需要注意避免数据竞争、死锁等问题,并合理拆分和组合任务,设置优先级、异常处理、超时处理以及终止和重试机制等。希望本文能够帮助大家更好地掌握Python中的多线程并发执行技术。 阅读详情

相关推荐

LabVIEW+数据库应用系列保姆级教程,第一篇数据库连接

目录LabVIEW连接数据库的方法连接MySQL连接Oracle,SQL Server,Access等 LabVIEW连接数据库的方法 1、创建udl(Universal Data Link)是通用数据连接文件。界面操作,简单快捷。 2、编写连接字符串。需要熟悉连接字符串的结构,容易出错。 3、其他… 本教程教你使用第1种方法,也是最简单、最常用的方法。 连接MySQL 1、在MySQL Installer内安装MySQL Connector/ODBC,建议安装32位(X86),如下图: 2、创建ODBC

wwplh5520370的博客 1万+

.net mysql 多线程_基于.NET的多线程编程入门

using System;using System.Threading;namespace SynchronizationThreadsExample{class SynchronizationThreadsExample{private int counter = 0;static void Main( ) {SynchronizationThreadsExample STE = new Syn...

weixin_39980360的博客 173

一文读懂资管系统里的“清算路径”:钱和券的“导航地图”

简单来说,清算路径就是给每一笔交易预设好的“导航路线”。钱从哪个银行账户出?通过哪家证券公司去买?用哪个股东账户去登记?买回来的股票记在谁的名下?“清算路径”就是把这一连串问题的答案提前配置好。它连接了银行托管户(钱的源头)、券商(交易的中介)和交易所(买卖的市场)。没有配好这条路,交易就无法闭环。清算路径是金融基础设施的缩影。资金如何安全地从银行流向市场;资产如何合法地归属到产品名下;交易数据如何在不同系统间流转。它是资管系统能够日复一日、准确无误地处理亿万级交易的基石。

m0_37607945的博客 235

Java实现多个线程一起并发执行

面试人员:用Java的多线程模拟一个赛马,马场上有10匹马,要求他们同时起跑 设计到的Java多线程技术:CountDownLatch或者CyclicBarrier /** * <p> * <p>Title:testCountDownLatch.java</p > * <p>Description: </p > * <p>Date:2020/10/20 14:53</p > * * @author wsh

Mick_^_^的博客 1万+

Informer:比Transformer更有效的长时间序列预测

目录 AAAI 2021最佳论文:比Transformer更有效的长时间序列预测 Background Why attention Methods:the details of Informer Solve_Challenge_1:最基本的一个思路就是降低Attention的计算量,仅计算一些非常重要的或者说有代表性的Attention即可,一些相近的思路在近期不断的提出,比如Sparse-Attention,这个方法涉及了稀疏化Attention的操作,来减少Attention计算量,然后涉及的

To be a better man 1万+

YOLOv8改进策略【卷积层】| CVPR-2023 部分卷积 PConv 轻量化卷积,降低内存占用

本文记录的是利用优化的目标检测方法研究。深度可分离卷积可以减少FLOPs,但会导致更高的内存访问,引起延迟并减慢整体计算。部分卷积利用逐点卷积处理通道冗余,减少模型计算量和内存访问量。Run, Don’t Walk: Chasing Higher FLOPS for Faster Neural Networks及其改进的实现代码如下: 四、创新模块 4.1 改进点⭐ 模块改进方法:直接加入(第五节讲解添加步骤)。模块加入如下:模块改进方法:基于的(第五节讲解添加步骤)。第二种改进方法是对中的进行改进,并将

Limiiiing的博客 1015

如何保证多个线程同时启动?

可以 wait()、notify() 实现;也可以使用发令枪 CountDownLatch 实现。 CountDownLatch 实现较简单,如下: package constxiong.interview; import java.util.concurrent.CountDownLatch; /** * 测试同时启动多个线程 * @author ConstXiong */ pu...

ConstXiong 1630

【Arduino 动手做】六舵机自平衡 Rotary Stewart 平台

《Arduino六舵机自平衡Rotary Stewart平台项目》 该项目展示了一个基于Arduino的六自由度Rotary Stewart平台,通过六个舵机实现动态平衡控制。设计采用激光切割框架和TAMIYA 70171套件,提供详细组装指南和开源固件(GitHub可获取)。开发者丹·罗耶分享了3D打印文件、视频演示及运动学优化需求,强调该平台可扩展应用于游戏控制(如Kerbal Space Program)或教育领域。项目链接包含完整资源包,鼓励用户参与改进并分享创作成果。该案例体现了Arduino在机

雕爷学编程 1088

java多线程同时执行方法

【代码】java多线程同时执行方法。

m0_74608954的博客 352

用 SAML 2.0 Bearer Assertion 配置 ABAP OAuth 2.0 令牌交换

摘要: SAP系统集成中,身份跨系统传递是关键挑战。OAuth 2.0的SAML 2.0 Bearer Assertion grant机制通过SAML断言换取访问令牌,实现安全身份传递。配置核心在ABAP的SOAUTH2事务码,需绑定可信SAML身份提供商(IdP)并指定访问范围。实际应用中,需确保SSL加密传输,正确配置SAML IdP信任关系,并为OAuth客户端分配专用系统用户。常见问题包括证书不匹配、权限配置不当等,需分层控制权限边界以保障安全。

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 835

【查找单入口空闲区域】-python实现-附ChatGPT解析

时间限制:1s 空间限制: 256MB 限定语言:不限题目描述:给定一个 m x n 的矩阵,由若干字符X’和 O构成,"X表示该处已被占据,O表示该处空闲,请找到最大的单入口空闲区域。空闲区域是由连通的O组成的区域,位于边界的O可以构成入口,单入口空闲区域即有且只有一个位于边界的o作为入口的由连通的O组成的区域如果两个元素在水平或垂直方向相邻,则称它们是“连通”的。第一行输入为两个数字,第一个数字为行数m,第二个数字列数n,两个数字以空格分隔,1

sinat_29950703的博客 242

java 线程同时启动_java多个线程同时启动的两种方式

【背景】今天遇到一个并发问题,为了在开发环境复现这个bug,需要让多个线程同时执行到某条语句。【解决方案】java1.5的concurrent包下的CyclicBarrier 和 CountDownLatch都能解决这个问题。不得不佩服Doug Lea!【方法1】使用CyclicBarrierpublic class TestCyclicBarrier {class Worker implemen...

weixin_35906775的博客 787

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

java同时启动线程_java多个线程同时启动的两种方式

【背景】今天遇到一个并发问题,为了在开发环境复现这个bug,需要让多个线程同时执行到某条语句。【解决方案】java1.5的concurrent包下的CyclicBarrier 和 CountDownLatch都能解决这个问题。不得不佩服Doug Lea!【方法1】使用CyclicBarrierpublic class TestCyclicBarrier {class Worker implemen...

weixin_39978749的博客 242

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

线程 实现的两种方法

实现Runnable接口,重写run方法 1 package thread; 2 3 public class MyRunnable implements Runnable { 4 5 private int i = 1; 6 7 @Override 8 public void run() { 9 10 fo...

weixin_30632899的博客 67

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

Java线程游戏:多个小球在界面移动

Java线程游戏:多个小球在界面移动

weixin_58879477的博客 1148

java自定义线程(两种方法)

两种方式实现自定义线程 同时运行两个线程 轮流调用两个线程

Julse的博客 3610

多线程两种创建方式

package cn.itcast.heima2; public class TraditionalThread { /** * @param args */ public static void main(String[] args) { Thread thread = new Thread(){ @Override public vo...

forlab的专栏 166

Java 创建线程

方法一 继承Thread类,重写run方法 创建子线程 public class Thread_01 extends Thread{ @Override public void run() { } } 在测试类中启动子线程 @Test public void test01(){ // 创建子线程对象 Thread_01 thread_01 = new Thread_01(); // 启动子线程 thr

SmallSweets的博客 421

java 线程 操作_java 线程操作

一、线程初始化两种方法:1.将类声明为Thread类的子类,重写Thead的run方法class PrimeThread extends Thread {long minPrime;PrimeThread(long minPrime) {this.minPrime = minPrime;}public void run() {// compute primes larger than minPri...

weixin_42311427的博客 181

创建和启动线程的两种方式

方式1:继承Thread类 步骤: 1):定义一个类A继承于java.lang.Thread类. 2):在A类中覆盖Thread类中的run方法. 3):我们在run方法中编写需要执行的操作:run方法里的代码,线程执行体. 4):在main方法(线程)中,创建线程对象,并启动线程. (1)创建线程类对象:                 A类   a  =  new   A类();

caidie_huang的博客 3万+

Java中同时启动多个线程并传入不同参数

thread传参的四种方式与threadLocal threadLocal thread局部变量有全局变量 同时启动多个线程 Java向线程传入参数的三种方法 public class Test { ThreadLocal<String> threadLocal=new ThreadLocal<String>(); @Test public void findOrderSplitDetailsTest() throws InterruptedException {

litongqiang的博客 2534

两种线程启动方式

一、利用Thread子类 //以下的代码代表一个线程,输入一百次message,这个message通过构造参数传入(这个线程就是Thread的子类) package threadTest; public class TwoThread extends Thread { private String message; public TwoThread(Strin...

求职之路 1696

java 启动线程的两种方式

启动线程肯定要用start()方法。当用start()开始一个线程后,线程就进入就绪状态,使线程所代表的虚拟处理机处于可运行状态,这意味着它可以由JVM调度并执行。这并不意味着线程就会立即运行。当cpu分配给它时间时,才开始执行run()方法(如果有的话)。START()是方法,它调用RUN()方法.而RUN()方法是你必须重写的. run()方法中包含的是线程的主体。 java启动线程

benpaobagzb的博客 1395
上一篇: 汽车之家基于 Flink 的数据传输平台的设计与实践
下一篇: kafka与RocketMQ对比
wrr-cat
博客等级 码龄9年 128粉丝 302原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值