`

Java多线程编程线程的协同、停止、暂停、继续等操作实现

 
阅读更多

      Java线程是Java执行的基本单元,单线程程序编写比较简单,但是处理效率不高。随着CPU核心数量的增加和对程序高性能的要求,多线程编程也成为必然的趋势。

      Java提供了至少三种实现线程的方式,一种是Runnable,一种是Thread,还有一种是线程池的方式。

1.Runnable方式:

Thread t = new Thread(new Runnable(){

public void run(){

//do something...

}

 

});

t.start();

2.Thread方式:

Thread t = new Thread(){

public void run(){

//do something...

}

}

t.start();

3.线程池的方式:

public class ThreadPoolEx {

private static BlockingQueue<Runnable> queue = new LinkedBlockingQueue<Runnable>(100);

private static ThreadPoolExecutor executors = new ThreadPoolExecutor(10,10,1000,TimeUnit.SECONDS,queue);

 

public static void main(String[] args) {

 

for(int i = 0;i<20;i++){

executors.execute(new RunnableTask(i));

}

}

/**

* 执行单元

*/

public static class RunnableTask implements Runnable{

 

private int index;

 

public RunnableTask(int index){

this.index = index;

}

 

@Override

public void run() {

System.out.println(index + "线程执行");

}

 

}

 

}

多线程在执行过程中,需要比单线程考虑很多问题。比如说线程安全;线程协同工作;线程停止,暂停,继续等工作。

一、线程安全

      线程安全就是在多线程程序执行过程中,多个线程会同时访问修改同一变量(全局变量),会导致变量状态不一致,导致运行错误。线程安全要保证共享变量在执行过程中的读写有序,串行执行,保证同一时刻所有线程看到的变量状态一致。

      保证线程安全的方法有很多,最常见的有三种,synchronized同步方法或者同步块,ReentrantLock显示加锁和读写锁,使用线程安全的原子对象操作变量的读写,例如AtomicInteger等。同步相关的操作这个不做介绍,参考其他文章。

二、线程协同工作

      在编程中会遇到多个线程同时完成一个事情,在这个过程中需要线程之间协同工作,例如等待其他线程完成,触发其他线程执行等。协同工作有CountDownLatch,CyclicBarrier等常用功能。

1.CountDownLatch

      适合场景是若干个线程全部执行完成后,再执行其他任务。

public static void main(String[] args) {

CountDownLatch latch = new CountDownLatch(4);

 

new TestThread(latch).start();

 

new TestThread(latch).start();

new TestThread(latch).start();

 

new TestThread(latch).start();

 

try {

latch.await();

System.out.println("执行完成");

} catch (InterruptedException e) {

e.printStackTrace();

}

}

 

public static class TestThread extends Thread{

 

CountDownLatch latch;

 

public TestThread(CountDownLatch latch){

this.latch = latch;

 

}

@Override

public void run() {

try {

Thread.sleep(1000);

latch.countDown();

} catch (InterruptedException e) {

e.printStackTrace();

}

}

}

2.CyclicBarrier

      适合场景是多个线程执行到同一位置后,同时执行,如果到达这个位置的线程数量不够则线程等待。

public static void main(String[] args) {

CyclicBarrier barrier = new CyclicBarrier(3);

 

new ThreadTest(barrier,1000).start();

new ThreadTest(barrier,2000).start();

new ThreadTest(barrier,3000).start();

 

System.out.println("主线程执行完成");

}

 

 

public static class ThreadTest extends Thread{

 

private CyclicBarrier cb;

 

private int waittime;

 

public ThreadTest(CyclicBarrier cb,int waittime){

this.cb = cb;

this.waittime = waittime;

}

 

public void run(){

try {

Thread.sleep(waittime);

cb.await();

} catch (InterruptedException e) {

e.printStackTrace();

} catch (BrokenBarrierException e) {

e.printStackTrace();

}

System.out.println("线程结束");

}

}

三、线程的停止、暂停、继续

      Java线程在设计之初没有考虑周全,Thread提供的stop,suspend,resume,destroy等方法都是线程不安全的,现在已经不推荐使用了。

1.stop方法会直接抛出ThreadDeath异常,导致线程终止,还有释放线程中持有的所有锁,如果线程对于共享变量进行了修改,使其处于不一致状态,其他线程再去访问这个对象就会产生意想不到的结果,甚至导致程序崩溃。

2.suspend,resume方法会导致线程的死锁,它会挂起线程持有的锁,如果一直这样可能导致其他需要该锁的线程死锁。

3.destroy方法压根就没有实现。

4.interrupt方法用于在线程没有响应或者处于阻塞状态时停止线程用的,它会抛出InterruptedException。在一些情况下可能不会响应interrupt方法,可以关闭相关资源方法促使线程结束,例如关闭Socket以结束线程。

5.线程停止的正确方法是定义一个volatile变量来标示线程是否停止,在线程执行中轮训这个变量来停止这个线程。例如下面这个例子。

 

public class ThreadStopEx extends Thread{

//标示线程是否停止标志

private volatile boolean  ISSTART = true;

 

@Override

public void run() {

 

while(ISSTART){

synchronized (this) {

try {

Thread.sleep(1000);

System.out.println("线程执行");

} catch (InterruptedException e) {

e.printStackTrace();

}

}

}

 

}

 

public void stopThread() {

ISSTART = false;

this.interrupt();

}

 

public static void main(String[] args) throws InterruptedException {

ThreadStopEx thread = new ThreadStopEx();

thread.start();

Thread.sleep(2500);

thread.stopThread();

}

 

}

6.线程的暂停和继续解决方法。线程的暂停和继续使用suspend/resume方法会有产生线程死锁问题,建议使用wait和notify来进行线程的暂停和继续。下面是例子。

public class ThreadSuspendResumeEx {

 

private static Object waitObject = new Object();

 

 

public static void main(String[] args) throws InterruptedException {

new ThreadTest(1).start();

new ThreadTest(2).start();

new ThreadTest(3).start();

//等待1000毫秒

Thread.sleep(1000);

synchronized (waitObject) {

waitObject.notify();

}

System.out.println("主线程1000毫秒后唤醒一个线程。");

//等待2000毫秒

Thread.sleep(2000);

System.out.println("主线程3000毫秒后唤醒全部线程。");

synchronized(waitObject){

waitObject.notifyAll();

}

 

}

 

 

 

public static class ThreadTest extends Thread{

//线程编号

private int index;

 

public ThreadTest(int index){

this.index = index;

}

@Override

public void run() {

synchronized(waitObject){

try {

waitObject.wait();

} catch (InterruptedException e) {

e.printStackTrace();

}

}

System.out.println(index + "线程执行");

}

}

}

源码见附件。

 

分享到:
评论
1 楼 天天向上666 2017-07-10  

相关推荐

    Java多线程编程实战指南 设计模式篇

    在Java编程领域,多线程和设计模式是两个至关重要的概念。它们对于构建高效、可扩展和健壮的系统起着关键作用。...通过实践和学习《Java多线程编程实战指南 设计模式篇》这本书,读者可以更深入地探索这一领域的奥秘。

    Java多线程的小例子——吃包子

    这个名为"Java多线程的小例子——吃包子"的示例,旨在帮助开发者直观地理解多线程的工作原理。下面我们将深入探讨该示例所涉及的核心知识点。 首先,多线程通常涉及到以下几个关键概念: 1. **线程(Thread)**:...

    单任务多线程下载程序

    综上所述,创建一个基于Java Swing的单任务多线程下载程序涉及到多线程编程、GUI设计以及文件操作等多个知识点。通过合理的设计和实现,这样的程序可以在保证用户界面响应性的同时,有效提升文件下载的速度和用户...

    一个Java多线程实现的坦克大战游戏.zip

    《Java多线程实现的坦克大战游戏》 Java语言在游戏开发领域虽然不如C++或Unity等工具常见,但它在教育场景和小型游戏制作中依然有其独特优势,尤其是在教学和学习多线程编程时。这个名为“坦克大战”的游戏项目就是...

    Java多线程下载Sample

    Java多线程下载技术是Java编程中的一种高效处理大文件下载的方法,尤其在现代网络环境中,用户对于数据传输速度有着高要求。通过使用多线程,可以将一个大文件分割成多个部分,同时从服务器获取,从而显著提高下载...

    DownTheradsUitl.zip_java 多线程下载

    在Java编程中,多线程下载是一项常见的任务,特别是在处理大文件或提高网络效率时。`DownThreadsUitl.zip`中的源代码`DownThreadsUitl.java`为我们提供了一个自定义实现的多线程下载工具,具备了指定下载线程数量、...

    40道常问的Java多线程面试题!.pdf

    Java多线程编程中还包括其他重要概念,如线程安全、锁机制(synchronized、Lock)、线程通信(wait/notify、BlockingQueue)、线程池(ExecutorService)等。理解和掌握这些知识对于成为熟练的Java开发者至关重要。...

    基于java的多线程与线程安全实践-基于Http协议的断点续传系统毕业设计与实现(源代码).zip

    标题中的“基于Java的多线程与线程安全实践”是指在Java编程环境中...综上所述,这个毕业设计涵盖了Java多线程编程、线程安全实践、HTTP协议应用以及文件断点续传的实现,对于学习和理解这些核心技术有很好的实践价值。

    Java线程技术精选

    死锁是并发编程中的一种常见问题,两个或更多线程相互等待对方释放资源,导致所有线程都无法继续执行。避免死锁的关键是正确管理和顺序获取锁。 10. **线程的调度-休眠**: `Thread.sleep()`方法让当前线程暂停...

    多线程使用原因以及例程

    - 在多线程环境下,为了实现线程间的协作和通信,Java提供了`wait()`、`notify()`和`notifyAll()`等方法。 - 这些方法必须在`synchronized`代码块或方法内部使用,并且针对同一个对象的监视器操作。 ```java ...

    操作系统中对于线程的同步与互斥问题的设计原理及代码

    操作系统中的线程同步与互斥是并发编程中的关键概念,它们确保了多线程环境下的程序正确性和资源安全。线程互斥是指当多个线程访问同一临界资源时,同一时刻只允许一个线程进行操作,以防止数据竞争和不一致的状态。...

    JAVA并发编程实践-线程执行-学习笔记

    总的来说,Java并发编程实践中的任务执行是一个涉及线程调度、线程池管理、任务生命周期控制、结果处理等多个方面的复杂主题。理解和掌握这些概念和技术,能够帮助开发者编写出更加高效、可靠的并发程序。

    一个基于Java的多线程可断点下载的URL资源下载器(Windows).zip

    标题中的“一个基于Java的多线程可断点下载的URL资源下载器(Windows)”指的是一个用Java编程语言实现的程序,它支持多线程下载和断点续传功能,并且是专为Windows操作系统设计的。这样的下载器可以极大地提高大文件...

    总结Java中线程的状态及多线程的实现方式

    Java中的线程状态与多线程实现 在Java编程中,线程是程序执行的最小单元,它允许程序同时执行多个任务。Java提供了两种主要的方式来创建和管理线程:直接继承`Thread`类和实现`Runnable`接口。线程的状态则描述了...

    java线程

    以上是Java线程的基础知识,涵盖了创建、状态、同步、中断、线程池等方面,理解并运用这些概念可以帮助开发者编写出更加高效和可靠的多线程程序。在实际开发中,还需要根据具体需求灵活运用,并注意线程安全和性能...

    多线程同步,互斥,联合,守护,计时器线程Timer

    在Java编程语言中,多线程是...通过研究这些例子,初学者可以更好地理解Java多线程编程,并掌握如何在实际项目中安全有效地利用多线程。每个示例代码都提供了具体的场景,有助于理论知识与实践相结合,提升编程技能。

    学习多线程使用这个笔记就够了

    线程编程是Java中一个重要的概念,尤其对于大型的、高并发的应用来说,理解并掌握多线程是必不可少的。...然而,多线程编程也涉及复杂性,例如死锁、活锁和饥饿等问题,需要深入学习和实践才能完全掌握。

    coroutines,协同并发的纯Java实现,AKA协同程序.zip

    在Java编程领域,协同程序(Coroutines)是一种轻量级的并发执行模型,它提供了一种更为高效且灵活的方式来管理程序中的并发操作。与传统的线程模型不同,协程更像是一种用户级的线程,它们不需要操作系统级别的切换...

Global site tag (gtag.js) - Google Analytics