并发和多线程(五)--线程相关属性和线程异常处理

1、线程id和name

线程id是线程的唯一标识,不可修改,而线程名称是可以修改的。

public static void main(String[] args) {
    Thread thread = new Thread();
    System.out.println("主线程ID为:"+Thread.currentThread().getId());
    System.out.println("主线程ID为:"+thread.getId());
    System.out.println("主线程name为:"+thread.getName());
    thread.setName("thread58");
    System.out.println("主线程name为:"+thread.getName());
}
结果:
主线程ID为:1
主线程ID为:12
主线程name为:Thread-0
主线程name为:thread58

从结果看到,主线程的id为1,所以线程的id也是从1开始的,而新建的子线程的id为12,而不是我们猜想的2。

通过查看源码,知道线程id的规则如下:

public long getId() {
    return tid;
}

//通过调用Thread构造器初始化Thread,而tid = nextThreadID()
public Thread() {
    init(null, null, "Thread-" + nextThreadNum(), 0);
}

private static synchronized long nextThreadID() {
    return ++threadSeqNumber;
}

  这里是++threadSeqNumber实现自增,那为什么子线程的id不是2呢,是因为Jvm在运行代码的时候还会启动别的线程帮助程序运行和处理,例如垃圾

收集器等,通过debug我们就可以看到。

  而线程的name值,只是对线程的命名,除了默认情况下的命名,我们还可以通过setName()修改,而且可以多个线程name相同。

public Thread() {
    init(null, null, "Thread-" + nextThreadNum(), 0);
}
private static synchronized int nextThreadNum() {
    return threadInitNumber++;
}

  通过源码看到,默认没有name的情况下,通过"Thread-" + nextThreadNum()进行命名,而这个方法是threadInitNumber++,所以从Thread-0开始。

2、守护线程

  对于jvm来说,一般我们创建的线程都是用户线程,除了用户线程就是守护线程,守护线程为了程序运行而服务,守护用户线程。一般来说,守护线程

被jvm启动,而用户线程被主线程启动。根本的区别就是,如果jvm发现没有当前没有用户线程在运行,jvm就会退出,守护线程对jvm退出没有影响。

  线程类型默认继承父线程,例如,在main方法中创建一个线程,主线程就是用户线程,所以被创建的线程默认也是用户线程。同样的,守护线程创建的

线程也是守护线程。

//判断当前线程是否Wie守护线程
public final boolean isDaemon() {
    return daemon;
}
//设置当前线程为守护线程。true,守护线程,false,用户线程
public final void setDaemon(boolean on) {
    checkAccess();
    if (isAlive()) {
        throw new IllegalThreadStateException();
    }
    daemon = on;
}

PS:

  开发过程中,不要将线程设置为守护线程,一旦设置为守护线程,jvm发现没有用户线程在运行,就直接关闭了,就会导致我们的程序没有执行完就

关闭了。

3、线程优先级

  线程优先级是指线程启动执行的优先级,对于Java来说,一共10个优先级,默认为5。准确的说,线程优先级也是继承父类优先级,如果你把主函数设置

为8,新建的子线程默认也是8.

/**
 * The minimum priority that a thread can have.
 */
public final static int MIN_PRIORITY = 1;

/**
 * The default priority that is assigned to a thread.
 */
public final static int NORM_PRIORITY = 5;

/**
 * The maximum priority that a thread can have.
 */
public final static int MAX_PRIORITY = 10;

//设置线程优先级
public final void setPriority(int newPriority) {

}

//获取线程优先级
public final int getPriority() {
    return priority;
}

  开发中,我们不应该依赖线程优先级,因为我们在使用多线程的时候,发现优先级高的线程不一定比优先级低的线程先执行,只能说概率更高而已。

而且,1-10的优先级只是jvm的划分,总归要和OS挂钩的,不同的OS对优先级的划分不同,需要进行映射。例如Windows有7个优先级,1,2对1,3,4对

2。。。而Linux系统下Java线程优先级会被忽略,不能起作用。在solaris系统中,又是不同的。

  设置线程优先级,还有可能带来的问题,就是某些优先级低的线程可能一直无法获得CPU使用权,也就是一直保持"饥饿"状态。所以,综上,完全不

建议修改线程优先级。

4、如何捕获线程异常?

public static void main(String[] args) {
    Thread thread = new Thread(new ThreadClass());
    thread.start();
    for (int i = 0; i < 100; i++) {
        System.out.println(i);
    }
}

@Override
public void run() {
    throw new RuntimeException();
}

  通过上面的代码的运行,可以看到,子线程发生异常,主线程还是继续运行,如果运行在服务器上面,可能都不知道程序有出现过异常。所以,我们需要

对Thread的代码进行异常处理,例如try catch。

try catch处理线程异常:

public static void main(String[] args) {
    Thread thread = null;
    Thread thread1 = null;
    Thread thread2= null;
    Thread thread3 = null;
    try {
        thread = new Thread(() -> {
            throw new RuntimeException();
        });
        thread1 = new Thread(() -> {
            throw new RuntimeException();
        });
        thread2 = new Thread(() -> {
            throw new RuntimeException();
        });
        thread3 = new Thread(() -> {
            throw new RuntimeException();
        });
    } catch (RuntimeException e) {
        e.printStackTrace();
    }

    thread.start();
    thread1.start();
    thread2.start();
    thread3.start();

    for (int i = 0; i < 100; i++) {
        System.out.println(i);
    }
}

  四个线程都发生异常,我们通过try catch去处理,发现还是同样的结果。一个线程抛出异常,其他三个还有主线程还是会继续执行。

正确的方式:

明天再写,困了!

原文地址:https://www.cnblogs.com/huigelaile/p/11749209.html

时间: 2024-10-08 01:49:29

并发和多线程(五)--线程相关属性和线程异常处理的相关文章

Python中并发、多线程等

1.基本概念 并发和并行的区别: 1)并行,parallel 同时做某些事,可以互不干扰的同一时刻做几件事.(解决并发的一种方法) 高速公路多个车道,车辆都在跑.同一时刻. 2)并发 concurrency 同时做某些事,一个时段内有事情要处理.(遇到的问题) 高并发,同一时刻内,有很多事情要处理. 2.并发的解决 1)队列.缓冲区 排队就是把人排成队列,先进先出,解决了资源使用的问题. 排成的队列,其实就是一个缓冲地带,就是缓冲区. Queue模块的类queue.lifoqueue.prior

APUE: 线程相关库函数

线程有时称为轻权进程. 进程的所有信息对该进程的所有线程都是共享的. 每个线程有一个线程ID,线程ID只在它所属的进程环境中有效. 线程从进程继承的东西: 进程ID 地址空间 浮点环境 信号屏蔽字(不包括未决的信号集) 线程间共享的东西: 进程指令 大部分数据 信号处理程序和信号处理 当前工作目录 用户ID和组ID 线程间独立的东西: 线程ID 寄存器集合 栈 errno 信号掩码 优先级 所有线程函数返回类型为int的成功返回0,失败返回错误码,不设置errno. 线程编程需要链接库: -lp

线程执行流程与线程函数

1.线程的创建.终止及控制:        任何进程在启动时就已有了一个主线程,如果需要再生成线程则使用pthread_create函数,在该函数中可以指定线程的属性.线程例程.传给线程例程的参数.线程例程是一个用户自定义的函数,及线程执行的代码.当线程例程返回时,线程则结束运行,也可以显示调用pthread_exit来退出.线程在创建后可以用pthread_self函数获取线程ID.函数pthread_join使得进程等待线程的终止,调用pthread_join后进程将被挂起,直到指定的某个线

“全栈2019”Java多线程第三十五章:如何获取线程被等待的时间?

难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java多线程第三十五章:如何获取线程被等待的时间? 下一章 "全栈2019"Java多线程第三十六章:如何设置线程的等待截止时间 学习小组 加入同步学习小组,共同交流与进步. 方式一:关注头条号Gorhaf,私信"Java学习小组". 方式二:关注公众号Gorhaf,回复&qu

并发编程(六)Object类中线程相关的方法详解

一.notify() 作用:唤醒一个正在等待该线程的锁的线程 PS : 唤醒的线程不会立即执行,它会与其他线程一起,争夺资源 /** * Object类的notify()和notifyAll()方法详解 */ public class MyNotify { // 在多线程间共享的对象上使用wait private String[] shareObj = {"true"}; public static void main(String[] args) { MyNotify test =

APUE学习之多线程编程(三):线程属性、同步属性

一.线程属性 可以使用pthread_attr_t结构修改线程默认属性,并这些属性和创建的线程练习起来,可以使用pthread_att_init函数初始化pthread_attr_t结构,调用pthread_attr_init后,pthread_attr_t结构所包含的就是操作系统实现支持的所有线程属性的默认值. pthread_attr_destroy用于销毁属性对象,释放资源. #include <pthread.h> int pthread_attr_init(pthread_attr_

Java多线程与并发——线程生命周期和线程池

线程生命周期:  线程池:是预先创建线程的一种技术.线程池在还没有任务到来之前,创建一定数量的线程,放入空闲队列中,然后对这些资源进行复用.减少频繁的创建和销毁对象. java里面线程池的顶级接口是Executor,是一个执行线程的工具. 线程池接口是ExecutorService. java.util.concurrent包:并发编程中很常用的实用工具类 Executor接口:执行已提交的Runnable任务的对象. ExecutorService接口:Executor提供了管理终止的方法,以

Java多线程——&lt;五&gt;后台线程(daemon)

一.后台线程(守护线程) 学一个东西,最重要的一点就是,为什么要用它? 后台线程区别于普通线程,普通线程又可以称为用户线程,只完成用户自己想要完成的任务,不提供公共服务.而有时,我们希望编写一段程序,能够提供公共的服务,保证所有用户针对该线程的请求都能有响应. 仔细来看下后台线程的定义:指在程序运行的时候在后台提供一种通用服务的线程,并且这种线程并不属于程序中不可或缺的部分. 二.实现后台线程 1.我们先定义任务及响应的线程 定义任务:Thread.yield();让线程暂停一段时间 class

java高并发编程(五)线程池

摘自马士兵java并发编程 一.认识Executor.ExecutorService.Callable.Executors /** * 认识Executor */ package yxxy.c_026; import java.util.concurrent.Executor; public class T01_MyExecutor implements Executor { public static void main(String[] args) { new T01_MyExecutor(