IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> Java 多线程基础 -> 正文阅读

[Java知识库]Java 多线程基础

进程与线程

  • 进程

进程是操作系统结构的基础,是程序在一个数据集合上运行的过程,是系统进行资源分配和调度的基本单位。进程可以被看作程序的实体,同样,它也是程序的容器。

  • 线程

线程是操作系统调度的最小单元,也叫作轻量级进程。在一个进程中可以创建多个线程,这些线程都拥有各自的计数器、堆栈和局部变量等属性。

使用多线程的优势

  • 使用多线程可以减少程序的响应时间

如果某个操作很耗时,或者陷入长时间的等待,此时程序将不会响应鼠标和键盘等的操作,使用多线程后可以把这个耗时的操作分配到一个单独的线程中执行,从而使程序具备了更好的交互性。

  • 与进程相对,线程创建和切换开销更小,同时多线程在数据共享方面效率非常高。
  • 多CPU 或者多核计算机本身就具备执行多线程的能力。

如果使用单个线程,将无法重复利用计算机资源,这会造成资源的巨大浪费。在多CPU计算机中使用多线程能提高CPU的利用率。

  • 使用多线程能简化程序的结构,使程序便于理解和维护。

线程的状态

  • New

新创建状态。线程被创建,还没有调用start方法,在线程运行之前还有一些基础工作要做。

  • Runnable

可运行状态。一旦调用start方法,线程就处于Runnable 状态。一个可运行的线程可能正在运行也可能没有运行,这取决于操作系统给线程提供运行的时间。

  • Blocked

阻塞状态。表示线程被锁阻塞,它暂时不活动。

  • Waiting

等待状态。线程暂时不活动,并且不运行任何代码,这消耗最少资源,直到线程调度器重新激活它。

  • Timed waiting

超时等待状态。和等待不同的是,它是可以在指定的时间自行返回的。

  • Terminated

终止状态。表示当前线程已经执行完毕。导致线程终止有两种情况:(1)run方法执行完毕正常退出;(2)因为一个没有捕获取得异常而终止了run 方法,导致线程进入终止状态。

在这里插入图片描述

线程创建后,调用Thead的start方法,开始进入运行状态,当线程执行wait方法后,线程进入等待状态,进入等待状态的线程需要其他线程通知才能返回运行状态。超时等待相当于在等待状态加上了时间限制,如果超过时间限制,则线程返回运行状态。当线程调用到同步方法时,如果线程没有获得锁则进入阻塞状态,当阻塞状态的线程获取到锁时则重新回到运行状态。当线程执行完毕或者遇到意外异常终止时,都会进入终止状态。

创建线程

  • 继承Thread类,重写run()方法
public class ThreadExample2 extends Thread{

	public static void main(String[] args) {
		Thread mThread=new ThreadExample2();
		mThread.start();
	}
	
	@Override
	public void run() {
		 System.out.print("thread excute");		
	}

}
  • 实现Runnable接口,并实现该接口的Run()方法 (推荐)
public class ThreadExample {

	public static void main(String[] args) {
      ExRunnable runnable=new ExRunnable();
      Thread mThread=new Thread(runnable);
	  mThread.start();
	}
	
}
public class ExRunnable implements Runnable{
	@Override
	public void run() {
        System.out.print("thread excute");		
	}

}
  • 实现Callable接口,重写call()方法

Callable接口是属于Executor框架中的功能类。Callable可以在任务接受后提供一个返回值,Runnable无法提供这个功能。

  1. Callable中的call()方法可以抛出异常,而Runnable的run()方法不能抛出异常。
  2. 运行Callable可以拿到一个Future对象,Future对象表示异步计算的结果,它提供了检查计算是否完成的方法。
  3. 由于线程属于异步计算模型,因此无法从别的线程中得到函数的返回值,在这种情况下就可以使用Future来监视目标线程调用call()方法的情况。但调用Future的get()方法以获取结果时,当前线程就会阻塞,直到call()方法返回结果。
public class ThreadExample {

	public static void main(String[] args) {
	  
	  ExCallable mCallable=new ExCallable();
	  ExecutorService mExecutorService=Executors.newSingleThreadExecutor();
	  Future<String> mFuture=mExecutorService.submit(mCallable);
	  try {
		System.out.println(mFuture.get());
	  } catch (Exception e) {
		e.printStackTrace();
	  }
	}
	
}

public class ExCallable implements Callable<String> {

	@Override
	public String call() throws Exception {
		// TODO Auto-generated method stub
		return "thread excute";
	}

}

线程中断

当线程的run 方法执行完毕,或者在方法中出现没有捕获的异常时,线程将终止。interrupt方法可以用来请求中断线程。当一个线程调用interrupt方法时,线程的中断标识位为true,线程会不时地检测这个中断标识位,以判断线程是否应该被中断。

 // 判断线程是否被中断
  Thread.currentThread().isInterrupted();

抛出InterruptedException 异常后,两种处理方法:

void task(){
     ....
     try{
        sleep(50)
     }catch(InterruptedException e){
        Thread.currentThread().interrupted(); 
     }
 }

在catch子句中,调用Thread.currentThread().interrupted()来设置中断状态(因为抛出异常后中断标识位会复位,即重新设置为false),让外界通过Thread.currentThread().isInterrupted() 来决定是否终止还是继续下去。

void task() throw InterrupetedException{
     sleep(50); 
  }

不用try来捕获异常,让方法直接抛出,这样调用者可以捕获这个异常。

中断线程Example

public class StopExampleThread {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
    
		try {
			InterruptedRunnable mRunnable=new InterruptedRunnable();
			Thread thread=new Thread(mRunnable,"threadDemo");
			thread.start();
			TimeUnit.MILLISECONDS.sleep(10);
			thread.interrupt();
		} catch (InterruptedException e) {
			// 抛出InterruptedException后中断标志被清除
			// 再次调用interrupt恢复中断
			Thread.currentThread().interrupt();
		}
		
	}
	
	static class InterruptedRunnable implements Runnable{

		int i=0;
		@Override
		public void run() {
			// TODO Auto-generated method stub
			while(!Thread.currentThread().isInterrupted()) {
				i++;
				System.out.println("i="+i);
			}
			System.out.println("stop");			
		}
		
	}

小结:

  • 如果一个线程处于阻塞状态,线程在检查中断标识位时,如果发现中断标识位为true,则会在阻塞方法调用处抛出InterruptedException 异常,并且在抛出异常前将线程的中断标识位复位,即重新设置为false。
  • 被中断的线程不一定会终止,中断线程是为了引起线程的注意,被中断的线程可以决定如何去响应中断。如果是比较重要的线程则不会理会中断,而大部分情况则是线程会将中断作为一个终止的请求。
  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2021-08-25 12:04:45  更:2021-08-25 12:05:13 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 8:51:53-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码