`

Java多线程高并发基础篇(三)-线程的生命周期及基本操作举例

 
阅读更多

在说线程之前,有必要说下线程与进程之间的关系。

附oracle官网链接:https://docs.oracle.com/javase/tutorial/essential/concurrency/procthread.html

这里有原版的关于线程和进程的介绍,我们只简单介绍下,作为知识普及。

一.进程与线程的关系

1.进程:进程一般情况下是程序或者应用程序的同义词,是系统进行资源和调度的基本单位,是操作系统结构的基础。它有自己独立的内存空间,换句话说,它有一套私有的运行时资源。在现代面向线程的计算机结构中,进程作为了线程的容器存在,而进程变为了程序的代名词。但是要注意的是,Java虚拟机的大多数实现都是作为一个进程运行的。

2.线程:在面向线程的计算机结构中,线程有时被称为轻量级的进程。在进程中,各个线程共享进程的资源(内存和文件)。每个应用程序都至少包含一个线程。

 

3.为什么要使用线程进行并发程序设计?

因为相对于进程来说,线程的切换和调度的成本远远小于进程。

 

二.线程的生命周期

既然要说线程,就免不了说下线程的生命周期,也就是各个状态之间的转换。



 



 可以看到,在源码Thread类中定义了一个枚举类型State,这个State就是线程生命周期中的各种状态。

根据英文注释,我们可以知道各个状态的含义,这里不细说。

附线程的状态转换图:

后续篇我们逐渐详述介绍这几种状态之间的转换过程。

 


 三.线程的基本操作(这些都很简单,不在这里详细说)

1.新建线程

新建一个线程有两种方式:一种是继承Thread类,并重写Thread类的run方法(因为你要在run方法中实现你的业务逻辑);另外一种是实现Runnable接口。

 

public class ThreadDemo extends Thread {
	@Override
	public void run() {
		// TODO Auto-generated method stub
		super.run();
		System.out.println("继承Thread实现线程执行");
	}
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		new ThreadDemo().start();
	}

}
 

 

public class RunnableDemo implements Runnable {

	@Override
	public void run() {
		System.out.println("我的第一个线程程序!");
	}

	public static void main(String[] args) {
		new Thread(new RunnableDemo()).start();
	}

}
 其实通过源码来看,实际就是一种方式,直接实现Runnable接口。我们可以看下Thread源码类中:
 所以关于如何新建线程的方式的讨论可以休矣。
2.废弃方法(可以不看了)
stop方法:暴力终止,会出现数据不一致,废弃也在情理之中,被带有中断机制的方法代替了。
suspend:挂起方法,也被废弃了,是因为调用此方法后,线程挂起后不释放资源,并且线程的状态是RUNNABLE,可能会让我们误判当前的系统状态。
 resume:是与suspend配套使用的,但是如果它比suspend先执行,那线程永远挂着了,图就不截了。
3.中断方法:
有关中断的有三个方法:
①Thread类中的interrupt()方法是实例方法,它可以设置线程的中断标识(也就是说并不是调用这个方法就中断了)
②配合Thread类中的实例方法isInterrupted()来判断当前调用线程是否设置了中断标识。
③Thread类中的interrupted()也是用来判断当前的中断状态,但是会清除中断标识位
public static void main(String[] args) throws InterruptedException {
		Thread t = new Thread(){
			@Override
			public void run() {
				while(true){
		System.out.println(Thread.currentThread().interrupted());
					if(Thread.currentThread().isInterrupted()){
						System.out.println("我被中断了!");
						break;
					}
				}
			}
		};
		t.start();
		t.interrupt();
	}
 另外要注意的是,使用Thread.sleep(long xx)方法时(还有join方法,凡是报中断异常的方法),如果线程被中断,会抛出中断异常,并且标志位也会被清除。
public static void main(String[] args) throws InterruptedException {
		Thread t = new Thread(){
			@Override
			public void run() {
				while(true){
					try {
						System.out.println(Thread.currentThread().getName()+"|"+Thread.currentThread().isInterrupted());
						Thread.sleep(1000);
						System.out.println(Thread.currentThread().getName()+"|"+Thread.currentThread().isInterrupted());
					} catch (InterruptedException e) {
						e.printStackTrace();
						//如果要正确处理逻辑,这里要恢复中断标志位,重新进行中断
						//重新设置中断标志
						Thread.currentThread().interrupt();
					}
					if(Thread.currentThread().isInterrupted()){
						System.out.println("我被中断了!");
						break;
					}
				}
			}
		};
		t.start();
		t.interrupt();
	}
 
4.等待(wait)和通知(notify)
首先要知道,这两方法是Object类中的方法,也就是说任何类都继承了这两方法。
在一个线程中,当一个对象调用wait()方法后,当前线程就会等待在这个对象上。直到另外一个线程调用了obj.notify()方法后,才能解除等待。要注意的第一点,这里的对象是同一个!第二点,这个对象必须被用作监视器锁!第三点,等待的线程必须获得了监视器锁后才能执行,并不是说另一个线程执行了notify()方法后就能被唤醒了!
 
public class WaitNotifyDemo{
	final static Object obj = new Object();
	static class T1  extends Thread {
		@Override
		public void run() {
			synchronized (obj) {
				System.out.println(System.currentTimeMillis()+":T1 start!");
				try {
					obj.wait();
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				System.out.println(System.currentTimeMillis()+":T1 end!");
			}
		}
	}
	static class T2  extends Thread {
		@Override
		public void run() {
			synchronized (obj) {
				System.out.println(System.currentTimeMillis()+":T2 start!");
				obj.notify();
				try {
					Thread.sleep(2000);//为了看的明显,等待2s
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				System.out.println(System.currentTimeMillis()+":T2 end!");
			}
		}
	}
	public static void main(String[] args) {
		new T1().start();
		new T2().start();
	}

}
 
 5.线程的加入(join)和谦让(yield)
线程的加入:在一个线程A中调用线程B的join()方法,那么线程A就必须等线程B的逻辑执行完成后,才能继续往下执行自己A的逻辑。加入实际就是一起走的意思!下面例子,最后i肯定是100000.
public class ThreadJoinDemo{
	public volatile static int i = 0;
	static class T1  extends Thread {
		@Override
		public void run() {
			for(i=0;i<100000;i++);
		}
	}
	public static void main(String[] args) throws InterruptedException {
		T1 t1 = new T1();
		t1.start();
		t1.join();
		System.out.println(i);
	}

}
 线程资源让出-yield:Thread.yield()是一个静态的本地方法。让出的意思很明确,让出CPU资源。但是,让出了我还要争夺的!
 四.线程的分类管理
1.线程的分组-线程组
给线程分个组,起个好听的名字吧,方便管理,默认新建的线程所在的线程组是创建线程的父组。
public class ThreadGroupDemo implements Runnable{

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		ThreadGroup tg = new ThreadGroup("zhaodf");
		Thread t1 = new Thread(tg, new ThreadGroupDemo(), "T1");
		Thread t2 = new Thread(tg, new ThreadGroupDemo(), "T2");
		Thread t3 = new Thread(new ThreadGroupDemo());
		t1.start();
		t2.start();
		t3.start();
	}

	@Override
	public void run() {
		// TODO Auto-generated method stub
		System.out.println(Thread.currentThread().getThreadGroup().getName()+"_"+Thread.currentThread().getName());
		try {
			Thread.sleep(2000);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

}
 
2.守护线程:守护线程守护的是谁?守护的是用户线程,用户线程不存在了,它就没有意义了,因此也就停掉了。
public class Daemon {
	public static class DaemonT extends Thread{
		@Override
		public void run() {
			while(true){
				System.out.println(System.currentTimeMillis()+"_"+Thread.currentThread().getName()+"_i am alive");
				try {
					Thread.sleep(1000);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
	}
	
	/**
	 * @param args
	 * @throws InterruptedException 
	 */
	public static void main(String[] args) throws InterruptedException {
		// TODO Auto-generated method stub
		Thread t = new DaemonT();
		//必须在start方法之前设置守护线程,这样t变为守护线程,而主线程main成为用户线程。当主线程休眠2秒后,守护线程也退出
		//如果放在start之后,会抛出Exception in thread "main" java.lang.IllegalThreadStateException异常
		t.setDaemon(true);
		t.start();
		System.out.println(System.currentTimeMillis()+"_"+"主线程名称:"+Thread.currentThread().getName());
		Thread.sleep(2000);
	}

}
 
 3.线程的优先级:
线程的优先级并不能保证线程优先执行,这点要注意。
public class PriorityDemo{

	public static class HightPriority extends Thread{
		static int count = 0;
		@Override
		public void run() {
			// TODO Auto-generated method stub
			while(true){
				synchronized (PriorityDemo.class) {
					count++;
					if(count>10000){
						System.out.println("HightPriority is complete");
						break;
					}
				}
			}
		}

	}
	
	public static class LowerPriority extends Thread{
		static int count = 0;
		@Override
		public void run() {
			// TODO Auto-generated method stub
			while(true){
				synchronized (PriorityDemo.class) {
					count++;
					if(count>10000){
						System.out.println("LowerPriority is complete");
						break;
					}
				}
			}
		}
	}
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Thread high = new HightPriority();
		Thread low = new LowerPriority();
		//设置优先级并不能保证线程一定优先执行
		high.setPriority(Thread.MAX_PRIORITY);
		low.setPriority(Thread.MIN_PRIORITY);
		high.start();
		low.start();
	}

}
 
  • 大小: 34.8 KB
  • 大小: 30.8 KB
  • 大小: 33 KB
  • 大小: 15.1 KB
  • 大小: 3.8 KB
  • 大小: 26.7 KB
分享到:
评论

相关推荐

    Java多线程与并发库高级应用

    并发库高级应用\多线程\Java

    java 多线程并发实例

    在Java编程中,多线程并发是提升程序执行效率、充分利用多核处理器资源的重要手段。本文将基于"java 多线程并发实例"这个主题,深入探讨Java中的多线程并发概念及其应用。 首先,我们要了解Java中的线程。线程是...

    Java 多线程与并发(1-26)-Java 并发 - 理论基础.pdf

    Java 多线程与并发理论基础 Java 多线程与并发是 Java 编程语言中的一种机制,用于提高程序的执行效率和响应速度。多线程的出现是为了解决 CPU、内存、I/O 设备速度差异的问题,通过分时复用 CPU、缓存和进程、...

    Java多线程实战精讲-带你一次搞明白Java多线程高并发

    Java多线程实战精讲是Java开发者必备的技能之一,特别是在处理高并发场景时,它的重要性不言而喻。本文将深入探讨Java多线程的相关知识点,帮助你全面理解并掌握这一核心概念。 1. **线程基础** - **线程定义**:...

    Java多线程与高并发入门到精通-视频教程网盘链接提取码下载.txt

    综上所述,《Java多线程与高并发入门到精通》是一门全面涵盖Java多线程编程基础及高级技术的课程。无论您是初学者还是有一定基础的开发者,都能够从中获得宝贵的知识和经验。通过学习这门课程,您将能够掌握多线程的...

    Java多线程编程实战指南-核心篇

    《Java多线程编程实战指南-核心篇》是一本深入探讨Java并发编程的书籍,旨在帮助读者掌握在Java环境中创建、管理和同步线程的核心技术。Java的多线程能力是其强大之处,使得开发者能够在同一时间执行多个任务,提高...

    java多线程与高并发视频

    java多线程与高并发java多线程与高并发java多线程与高并发

    java多线程和并发.pdf

    Java多线程与并发编程是Java语言中用于处理多任务执行的关键技术,它能够帮助开发者设计出能够有效应对高并发请求的应用程序。在现代的线上(Online)和离线(Offline)应用中,合理利用多线程技术可以大幅提高系统...

    Java_多线程与并发编程总结.doc

    Java多线程与并发编程是Java开发中至关重要的一部分,它涉及到如何高效地利用CPU资源,以实现程序的并行执行。在操作系统层面,多任务和多进程是通过分配不同的内存空间来实现的,而线程则共享同一进程的内存,这...

    java多线程、并发及线程池介绍收藏的几篇文档

    Java多线程、并发以及线程池是Java编程中至关重要的概念,特别是在处理高并发、高性能的系统设计时。以下是对这些主题的详细说明: 1. **Java 程序中的多线程** - 多线程允许一个程序同时执行多个任务,提高程序...

    JAVA线程、线程池资料----下载不扣分,回帖加1分,欢迎下载,童叟无欺

    在多线程大师Doug Lea的贡献下,在JDK1.5中加入了许多对并发特性的支持,例如:线程池。.......................................JAVA线程、线程池资料----下载不扣分,回帖加1分,欢迎下载,童叟无欺JAVA线程、...

    Java多线程-线程的生命周期

    Java多线程中,线程的生命周期是编程中必须理解的重要概念。在JDK1.5之前,线程被划分为五个状态,分别是新建(New)、就绪(Runnable)、运行(Running)、阻塞(Blocked)和死亡(Dead)。在JDK1.5及之后,线程的...

    JAVA线程高级-线程按序交替执行

    在Java编程中,多线程是并发编程的重要组成部分,它允许程序同时执行多个任务,从而提高了系统的效率和响应性。然而,在某些场景下,我们可能需要控制线程的执行顺序,确保它们按照特定的顺序交替运行,这在并发编程...

    java 多线程编程实战指南(核心 + 设计模式 完整版)

    《Java多线程编程实战指南》这本书深入浅出地讲解了Java多线程的核心概念和实战技巧,分为核心篇和设计模式篇,旨在帮助开发者掌握并应用多线程技术。 1. **线程基础** - **线程的创建**:Java提供了两种创建线程...

    java 多线程操作数据库

    在当今高度并发的应用环境中,Java多线程技术被广泛应用于处理数据库操作,以提升系统的响应速度和处理能力。本文将基于一个具体的Java多线程操作数据库的应用程序,深入探讨其背后的原理、实现细节以及潜在的挑战。...

    java多线程并发

    本篇文章将深入探讨Java中的多线程并发机制,并通过具体的示例来帮助读者更好地理解和掌握这一重要概念。 #### 二、为什么需要多线程? 多线程技术的存在主要解决了计算机系统中资源利用率低下的问题。在没有多...

    图解java多线程设计模式-结城浩-完整高清带书签版本

    1. **线程基础**:书中首先介绍了Java中线程的基本概念,包括如何创建线程(通过继承Thread类或实现Runnable接口)、启动线程以及线程的生命周期状态(新建、运行、阻塞、等待、死亡)。 2. **线程同步**:为了解决...

Global site tag (gtag.js) - Google Analytics