Java线程的控制详解

1. join线程

在线程执行过程中,有时想让另一个线程先执行,比如将一大问题分割成许多小问题,给每一个小问题分配线程,但所有小问题处理完后再让主线程进一步操作。此时我们可以在主线程中调用其它线程的join()方法,以阻塞调用线程(在这里为主线程)。

示例代码:

代码如下:

package org.frzh.thread;
 
 public class JoinThread extends Thread{
     //提供一个有参构造器,用来设置线程的名字
     public JoinThread(String name) {
         super(name);
     }
    
     public void run() {
         for (int i = 0; i < 100; i++) {
             System.out.println(getName() + " " + i);
         }
     }
    
     public static void main(String[] args) {
         //启动子线程
         new JoinThread("新线程").start();
         for (int i = 0; i < 100; i++) {
             if (i == 20) {
                 JoinThread jt = new JoinThread("被join的线程");
                 jt.start();
                 //main线程调用了jt线程的join方法,则main线程必须等待jt执行完之后才能执行
                 try {
                     jt.join();
                 } catch (InterruptedException e) {
                     // TODO Auto-generated catch block
                     e.printStackTrace();
                 }
             }
             System.out.println(Thread.currentThread().getName() + " " +i);
         }
     }
 }

本来有三套线程(两条子线程和一main线程),当i=20后,main线程被阻塞必须等到“被join线程”执行完之后才有机会执行,所以此后只有两条线程执行。

join()方法的三种重载形式:

join():等待被join线程执行完;

join(long millis):等待被join线程执行最长为mills豪秒,在这之后即使被join线程没有执行完也不再等待;

join(long millis, int nanos):等待被join线程执行最长时间为millis毫秒+nanos微秒。(此方法基本用不上)。

2:后台线程

有一种线程,他是在后台运行,他的任务是为其他线程服务,这种线程被称为“后台线程”、“守护线程”或“精灵线程”。当所有前台线程都死亡后,后台线程会自动死亡。

示例代码:

代码如下:

package org.frzh.thread;
 
 public class DaemonThread extends Thread{
     public void run() {
         for (int i = 0; i < 1000; i++) {
             System.out.println(getName() + " " +i);
         }
     }
    
     public static void main(String[] args) {
         DaemonThread dt = new DaemonThread();
         //将此线程设置为后台线程
         dt.setDaemon(true);
         dt.start();
         for (int i = 0; i < 10; i++) {
             System.out.println(Thread.currentThread().getName() + " " + i);
         }
         //前台线程结束,那么后台线程dt也会结束,所以它执行不到999
     }
 }

主线程默认是前台线程,前台线程创建的子线程默认是前台线程,后台线程创建的子线程默认是后台线程。

3.线程睡眠(sleep):

前面的join方法是让调用线程等待被join线程执行完之后再继续执行,而sleep()方法是让调用线程阻塞一段时间后再重新进入就绪状态等待被调度。因此它通常用来暂停程序的执行。

示例代码:

代码如下:

package org.frzh.thread;
 
 import java.util.Date;
 
 public class SleepThread{
     public static void main(String[] args) {
         for (int i = 0; i < 10; i++) {
             System.out.println("当前时间:" + new Date());
             try {
                 Thread.sleep(1000);
             } catch (InterruptedException e) {
                 // TODO Auto-generated catch block
                 e.printStackTrace();
             }
         }
     }
 }

sleep()方法的两种重载方式:

static void sleep(long millis):让当前线程暂停millis毫秒,并进入阻塞状态。该方法会受到系统计时器和线程调度器的精度和准度的影响。

static void sleep(long millis, int nanos):暂停mills毫秒+nanos微秒,并进入阻塞状态,同样会受系统计时器和线程调度器的精度和准度的影响。基本不用。

4.线程让步(yield):

yield()方法和sleep方法有点类似,它同样可以使当前正在运行的线程暂停,但他不会阻塞该线程,只是将他转入就绪状态(注意不是阻塞状态)。yield()方法只会让和它同等优先级或更高优先级的线程有被执行的机会,所以某一线程调用该方法后可能又被重新调度回来继续执行。

示例代码:

代码如下:

package org.frzh.thread;
 
 public class YieldThread extends Thread{
     public YieldThread() {
        
     }
     public YieldThread(String name) {
         super(name);
     }
     public void run() {
         for (int i = 0; i < 100; i++) {
             System.out.println(getName() + " " +i);
             if (i == 20) {
                 //当前线程让步
                 Thread.yield();
             }
         }
        
     }
    
     public static void main(String[] args) {
         //启动两条并发线程
         YieldThread yt1 = new YieldThread("高级");
         //设置yt1为最高优先级
         yt1.setPriority(Thread.MAX_PRIORITY);
         yt1.start();
         YieldThread yt2 = new YieldThread("低级");
         yt2.setPriority(Thread.MIN_PRIORITY);
         yt2.start();
         /*
          * 如果不给线程设置优先级,则两个线程的优先级是相同的,所以两线程会交替执行,当调用yield后会让另一个线程执行;
          * 但是,给两个线程分别设置上述优先级之后,刚开始高级线程执行,当i=20时,调用yield,但由于yield方法只会
          * 给和它同优先级或更高优先级的线程执行机会,所以此时仍是高级线程执行,而不会让给低级线程
          */
     }
 }

5:改变线程的优先级

此举比较简单,只需调用调用实例方法setPriority(int priority)方法即可。每个线程默认与其父线程的优先级相同,main线程默认具有普通优先级(5)。java提供1~10个优先级,也可以使用三个静态常量:

MAX_PRIORITY:10

MIN_PRIORITY:1

NORM_PRIORITY:5

注意的是:尽管java提供10个优先级,但是不同的系统支持的优先级不一样,所以尽量避免直接使用1~10之间的数字,而使用静态常量,以保证具有良好的可移植性。

(0)

相关推荐

  • Java join 线程控制用法

    JDK说明: joinpublic final void join()                throws InterruptedException等待该线程终止. 抛出:InterruptedException - 如果任何线程中断了当前线程.当抛出该异常时,当前线程的中断状态 被清除测试代码: 复制代码 代码如下: public class MyThread extends Thread { public static void main(String[] args) throws

  • java控制线程运行

    1.线程的控制很常见,如文件传送到一半时,需要暂停文件传送,或终止文件传送,这实际上就是控制线程的运行. 2.线程有创建.可运行.运行中.阻塞.死亡5个状态. 创建:使用new运算符创建一个线程 可运行:使用start方法启动一个线程后,系统分配了资源 运行中状态:执行线程的run方法 阻塞:运行的线程因为某种原因停止继续运行 死亡状态:线程结束 3.传统方法的安全问题 Thread的stop(),suspend(),resume(),destroy()方法,因为不安全,可能造成死锁,已经不再使

  • java信号量控制线程打印顺序的示例分享

    复制代码 代码如下: import java.util.concurrent.Semaphore; public class ThreeThread { public static void main(String[] args) throws InterruptedException {  Semaphore sempA = new Semaphore(1);  Semaphore sempB = new Semaphore(0);  Semaphore sempC = new Semapho

  • Java线程的控制详解

    1. join线程: 在线程执行过程中,有时想让另一个线程先执行,比如将一大问题分割成许多小问题,给每一个小问题分配线程,但所有小问题处理完后再让主线程进一步操作.此时我们可以在主线程中调用其它线程的join()方法,以阻塞调用线程(在这里为主线程). 示例代码: 复制代码 代码如下: package org.frzh.thread;    public class JoinThread extends Thread{      //提供一个有参构造器,用来设置线程的名字      public

  • Java线程池 ThreadPoolExecutor 详解

    目录 一 为什么要使用线程池 二 线程池原理详解 2.1 线程池核心组成 2.2 Execute 原理 三 线程池的使用 3.1 创建线程池 3.1.1 自定义线程池 3.1.2 功能线程池 3.1.3 功能线程池存在的问题 3.2 向线程池提交任务 3.3 关闭线程池 3.4 自定义线程池需要考虑因素 一 为什么要使用线程池 对于操作系统而言,创建一个线程的代价是十分昂贵的, 需要给它分配内存.列入调度,同时在线程切换时要执行内存换页,清空 CPU 缓存,切换回来时还要重新从内存中读取信息,破

  • Java线程的全方位详解

    目录 什么是线程? 线程的几种创建方式? 线程的几种状态? 线程相关的核心方法及作用? ❤️‍大家好,我是贾斯汀,今天主要聊一聊关于线程的瓜!❤️‍ 先来看一下线程这张图线程的几种运行状态之间运行流程: 看不懂没关系,慢慢来学习,往下学习来继续了解一下~ 什么是线程? 线程是进程的一部分,是程序执行中的一条执行路线: 进程就是指程序在其自身地址空间的一次执行活动,是程序独立运行的基本单位: 一个进程可以包含多条线程,一个条线程对应一个进程中的一条执行路线. 线程的几种创建方式? 主要由四种方式创

  • Java 线程池ExecutorService详解及实例代码

    Java 线程池ExecutorService 1.线程池 1.1什么情况下使用线程池 单个任务处理的时间比较短. 将需处理的任务的数量大. 1.2使用线程池的好处 减少在创建和销毁线程上所花的时间以及系统资源的开销. 如果不使用线程池,有可能造成系统创建大量线程而导致消耗系统内存以及"过度切换"; 2.ExecutorService和Executors 2.1简介 ExecutorService是一个接口,继承了Executor, public interface ExecutorS

  • java 线程创建多线程详解

    Java 线程类也是一个 object 类,它的实例都继承自 java.lang.Thread 或其子类. 可以用如下方式用 java 中创建一个线程,执行该线程可以调用该线程的 start()方法: Tread thread = new Thread(); thread.start(); 在上面的例子中,我们并没有为线程编写运行代码,因此调用该方法后线程就终止了. 编写线程运行时执行的代码有两种方式:一种是创建 Thread 子类的一个实例并重写 run 方法,第二种是创建类的时候实现 Run

  • java线程同步操作实例详解

    本文实例讲述了java线程同步操作.分享给大家供大家参考,具体如下: java线程同步 public class Hello { public static void main(String[] args) { MyRun myRun0 = new MyRun(); new Thread(myRun0, "Thread0").start(); new Thread(myRun0, "Thread1").start(); new Thread(myRun0, &quo

  • Java线程死锁代码详解

    /** * @author hollis */ public class JStackDemo { public static void main(String[] args) { Thread t1 = new Thread(new DeadLockclass(true));//建立一个线程 Thread t2 = new Thread(new DeadLockclass(false));//建立另一个线程 t1.start();//启动一个线程 t2.start();//启动另一个线程 }

  • java线程优先级原理详解

    java 中的线程优先级的范围是1-10,默认的优先级是5.10最高. MIN_PRIORITY 1 MAX_PRIORITY 10 NORM_PRIORITY 5 优先级高的获得cpu的几率更大些,不是优先级高的就先执行完,线程优先级随机特性 在java中,线程的优先级具有继承性,例如A线程启动B线程,则A和B的优先级是一样的 线程创建后,可通过调用setPriority()方法改变优先级. public class Test5 { public static class TheadT ext

  • Java ExecutorService四种线程池使用详解

    1.引言 合理利用线程池能够带来三个好处.第一:降低资源消耗.通过重复利用已创建的线程降低线程创建和销毁造成的消耗.第二:提高响应速度.当任务到达时,任务可以不需要的等到线程创建就能立即执行.第三:提高线程的可管理性.线程是稀缺资源,如果无限制的创建,不仅会消耗系统资源,还会降低系统的稳定性,使用线程池可以进行统一的分配,调优和监控.但是要做到合理的利用线程池,必须对其原理了如指掌. 2.线程池使用 Executors提供的四种线程 1.newCachedThreadPool创建一个可缓存线程池

  • Java并发编程之详解CyclicBarrier线程同步

    CyclicBarrier线程同步 java.util.concurrent.CyclicBarrier提供了一种多线程彼此等待的同步机制,可以把它理解成一个障碍,所有先到达这个障碍的线程都将将处于等待状态,直到所有线程都到达这个障碍处,所有线程才能继续执行. 举个例子:CyclicBarrier的同步方式有点像朋友们约好了去旅游,在景点入口处集合,这个景点入口就是一个Barrier障碍,等待大家都到了才一起进入景点游览参观. 进入景点后大家去爬山,有的人爬得快,有的人爬的慢,大家约好了山顶集合

随机推荐