并发基础(一) 线程介绍

一、线程的简介

线程,有时被称为轻量级进程(Lightweight Process,LWP),是程序执行流的最小单元。一个标准的线程由线程ID,当前指令指针(PC),寄存器集合和堆栈组成。另外,线程是进程中的一个实体,是被系统独立调度和分派的基本单位,线程自己不拥有系统资源,只拥有一点儿在运行中必不可少的资源,但它可与同属一个进程的其它线程共享进程所拥有的全部资源。一个应用程序可以看做是一个进程,一个进程可以创建多个线程,进程的任务就是交给这些线程来完成。

线程基础知识点可以总结为几点:

  1. 线程是程序中的执行线程。java虚拟机允许应用程序并发地运行多个执行线程。
  2. 每个线程都有一个优先级,高优先级线程的执行优先于低级优先级线程。但不应该通过设置线程优先级的方式来安排线程的执行顺序,后续将会细说。
  3. 每个线程都可以或者不标志为一个守护线程。即在java中,线程分为两类:用户线程 和 守护线程。
  4. 当java虚拟机启动时,都会有一个非守护线程(即用户线程)启动运行。这个线程通常是调用指定类的main方法。简单来说,当你执行一个类的main方法时,其实是作为一个线程在运行,即为main线程。
  5. 线程在操作系统中是不拥有资源, 线程是共享进程的资源。即属于同一个进程的多个线程之间是对资源可能要进行互斥访问。这就要涉及到锁的概念。同时在JVM中,除了用锁来解决并发的问题外,还可以让每个线程拥有私有资源---线程副本(ThreadLocal),这样,线程就不需要竞争资源。

二、用户线程与守护线程
守护线程:
      守护线程则是用来服务用户线程的,可以简单理解为后台运行线程。(操作系统里面是没有所谓的守护线程的概念,只有守护进程一说,但是Java语言机制是构建在JVM的基础之上的,意思是Java平台把操作系统的底层给屏蔽起来,所以它可以在它自己的虚拟的平台里面构造出对 自己有利的机制,而语言或者说平台的设计者多多少少是受到Unix思想的影响,而守护线程机制又是对JVM这样的平台凑合,于是守护线程应运而生);
    守护线程使用的情况较少,但并非无用,举例来说,JVM的垃圾回收、内存管理等线程都是守护线程。还有就是在做数据库应用时候,使用的数据库连接池,连接池本身也包含着很多后台线程,监控连接个数、超时时间、状态等等。

注意:
1、JRE判断程序是否执行结束的标准是所有的前台执线程行完毕了,而不管后台线程的状态,因此,在使用后台线程候一定要注意这个问题。
也就是说,当进程中所有非守护线程已结束或退出时,即使仍有守护线程在运行,进程依旧会结束。
也就是说,当程序结束时,守护线程有可能依然未退出。
2、基于第一点,守护线程是不能用于逻辑业务计算的,否则很可能还没有计算出结果,程序就结束了。

守护线程的设置:
  默认情况下,创建的线程默认是用户线程。如果要将此线程变成守护线程,则要在线程启动前调用Thread 类的 setDemo()方法,标志为守护线程。

setDemo()方法详解:

public final void setDaemon(boolean on)将该线程标记为守护线程或用户线程。当正在运行的线程都是守护线程时,Java 虚拟机退出。    
  该方法必须在启动线程前调用。    

  该方法首先调用该线程的 checkAccess 方法,且不带任何参数。这可能抛出 SecurityException(在当前线程中)。    


  参数: 
    on - 如果为 true,则将该线程标记为守护线程。    
  抛出:    
    IllegalThreadStateException - 如果该线程处于活动状态。    
    SecurityException - 如果当前线程无法修改该线程。 
  另请参见: 
    isDaemon(), checkAccess()

例子:

//这是一个很简单的线程,没有指定任何的任务
	Thread t =new Thread();
	//判断刚创建的线程t是不是守护线程
	if(t.isDaemon()){
		System.out.println("线程是守护线程");
	}else{
		System.out.println("线程是用户线程");
	}
	
	//将线程t设置为 守护线程
	t.setDaemon(true);
	//线程启动,注意:必须在线程启动前调用setDaemon()才有效
	t.start();

运行结果:
    线程是用户线程

原文地址:https://www.cnblogs.com/jinggod/p/8484674.html