Java-多线程-基础

本文介绍了Java多线程的基础知识,包括基于Runnable接口和Thread类的多线程创建,线程的状态转换,设置线程优先级,中断、安插和停止线程的方法。还详细讨论了Daemon线程,线程组的创建与作用,以及如何处理线程未捕获的异常。
摘要由CSDN通过智能技术生成

 

  • #Java多线程基础

    @基于Runnable接口、Thread类的多线程
        --->Demo样例


import static java.lang.System.in;
import static java.lang.System.out;
import java.util.Scanner;
import java.text.DecimalFormat;

public class Temp{
    public static void main(String... args) throws InterruptedException{
		//通过Thread调用实现了runnable接口的类所生产的实例
        Runnable runnerA = new Runnable(){
			public void run(){
				int i=10;
				while(i-->0){
					out.println("runnerA's step:"+i+"\t#"+Thread.currentThread().getState());
				}
			}
		};
		Thread threadA = new Thread(runnerA);
		//直接继承Thread类
		Thread threadB = new Thread(){
			public void run(){
				int i=200;
				while(i-->0){
					out.println("runnerB's step:"+i);
					out.println("threadB中观察threadA的状态为:"+threadA.getState());
				}
			}
		};
		//类似于直接继承Thread类,但方式是通过lambda表达式来设计
		new Thread(()->{
			int i=20;
			while(i-->0) out.println("runnerC's step:"+i);
		}).start();
		out.println("启动threadA前:"+threadA.getState());
		threadA.start();
		out.println("启动threadA后:"+threadA.getState());
		threadB.setDaemon(true);	
		threadB.start();	
		//Thread.sleep(100);
		
		
    }
}


    @普通线程与Daemon线程
        在多线程的应用中,JVM会在所有非Daemon线程结束之后中止。Daemon线程一般用作为服务线程,常见的如JVM中的GC线程就是一个Daemon线程。普通线程(Thread类)可以通过setDaemon()方法设置为Daemon线程。(必须在执行start()调用前设置才有效)
    
    @线程的基本状态
        通过Thread的getState()调用可以获取到线程的基本状态(6种)如下:
            1.NEW 
            尚未启动的线程处于此状态。 
            2.RUNNABLE 
            在Java虚拟机中执行的线程处于此状态。 
            3.BLOCKED 
            被阻塞等待监视器锁定的线程处于此状态。 
            4.WAITING 
            正在等待另一个线程执行特定动作的线程处于此状态。 
            5.TIMED_WAITING 
            正在等待另一个线程执行动作达到指定等待时间的线程处于此状态。 
            6.TERMINATED 
            已退出的线程处于此状态。 
            
    @设置线程的优先权
        通过Thread的setPriority()设置线程的优先级,优先级的范围必须大于等于Thread.MIN_PRIORITY(1),小于等于Thread.MAX_PRIORITY(10),默认是Thread.NORM_PRIORITY(5),不在范围内会抛出异常。线程的优先级越高,相同条件下有限被排入CPU。
    
   @中止线程的blocked状态
        通过其它线程调用对应线程的interrupt()方法,可以使对应的线程从blocked状态退出来,但对应线程会抛出IterruptedException。
        --->Demo样例


import static java.lang.System.in;
import static java.lang.System.out;
import java.util.Scanner;
import java.text.DecimalFormat;

public class Temp{
    public static void main(String... args) throws InterruptedException{
		Thread tA = new Thread(()->{
			out.println("tA is running...");
			try{
				while(true){
					Thread.sleep(5000);
					out.println("...");
				}
			}catch(InterruptedException e){
				out.println("tA catch ExceptionMsg:"+e.toString());
			}
			out.println("tA is over");
		});
		Scanner scan = new Scanner(in);
		tA.start();
		out.println("now, input something and pass 'enter'");
		scan.next();
		tA.interrupt();
		out.println("main is over");
		
    }
}

@安插线程
        当前线程正在运行时,可以通过join()方法安插其它线程进来,等安插的线程完成后再继续运行之前的线程。join()方法也可以指定安插线程的最大运行时间,到了最大时间会强行结束安插线程。
        --->Demo样例


import static java.lang.System.in;
import static java.lang.System.out;
import java.util.Scanner;
import java.text.DecimalFormat;

public class Temp{
    public static void main(String... args) throws InterruptedException{
		Thread tA = new Thread(()->{
			out.println("tA is running...");
			int i=10;
			while(i-->0) out.println("subThread ...");
			out.println("tA is over");
		});
		out.println("main is start...");
		tA.start();
		tA.join();
		int i=20;
		while(i-->0) out.println("main ...");
//tA.start(); //运行结束后,不允许再次调用start方法,否则会抛出IllegalThreadStateException
		out.println("main is over");
		
    }
}

@停止线程
        线程运行结束后,进入TERMINATED 状态,这时不允许再次调用start()方法,否则会抛出IllegalThreadStateException。
        线程的结束,应该设计合理的运行流程,让其自行结束。或者通过设计特殊参数,使得线程在参数变更后自行结束。
        (注释有@Deprecated的stop方法不推荐使用,因为其已经被定义为过时的)
        

  • #线程组

    每个线程都有所属的一个线程组(ThreadGroup)。在创建一个线程时,若没有指定其所属的线程组,则默认是属于当前创建其的线程所属的线程组。
    获取当前线程所属的线程组:
    Thread.currentThread().getThreadGroup().getName();
    需要注意的是,线程的线程组一旦指定就无法更改。
    
    @创建线程组
        指定线程组名称:
        ThreadGroup  group1 = new ThreadGroup("group1");
        指定线程组名称及其父线程组:
        ThreadGroup  group2 = new ThreadGroup(group1, "group2");
        
    @线程组的作用
        线程组的一些方法可以对群组内的所有线程产生作用。
        例如:
        interrupt():可以中断群组中所有的线程;
        setMaxPriority():设定群组中所有线程的最大优先权(本来就有更高优先权的线程不受影响);
        
    @常见方法的使用
        activeCount():获取当前群组中所有线程的数量;
        enumerate():传入一个Thread数组,将群组中的所有线程复制到数组中;
        uncaughtException():群组中某个线程发生异常而未捕获时,JVM会调用其所属群组中的这个方法。

--->通过Thread的setUncaughtExceptionHandler()设置未捕获异常的处理调用,Demo举例


import static java.lang.System.in;
import static java.lang.System.out;
import java.util.Scanner;
import java.text.DecimalFormat;

public class Temp{
    public static void main(String... args) throws InterruptedException{
		ThreadGroup group = new ThreadGroup("groupTest");
		Thread thread1 = new Thread(group, ()->{
			throw new RuntimeException("thread--1(通过setUncaughtExceptionHandler设置了异常处理方式) 运行时异常测试");
		});
		thread1.setUncaughtExceptionHandler((thread, throwable)->{
			out.println(thread.getName()+"--->"+ throwable.getMessage());
		});
		new Thread(group, ()->{
			throw new RuntimeException("thread--2 运行时异常测试");
		}).start();
		thread1.start();
				
    }
}

@线程未捕获异常调用的流程

未捕获异常会由线程实例setUncaughtExceptionHandler()设定的Thread.UncaughtExceptionHandler实例处理,之后是线程的ThreadGroup,然后才是默认的Thread.UncaughtExceptionHandler。

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值