Java多线程

目录

线程

线程的创建方式

[1. 继承Thread类](#1. 继承Thread类)

[2. 实现Runnable接口](#2. 实现Runnable接口)

3.继承TimerTask,定时线程

4.带有返回值的线程,Callable

[5.线程池 ExcuterService](#5.线程池 ExcuterService)

线程的生命周期

对线程的调度

沉睡-Thread.sleep()

让步-Thread.yeild()

合并-Thread.join()

线程的优先级


线程

一个进程有多个线程(进程是一个独立的工作任务和单元),线程由JVM(java虚拟机)控制。

协程:一个由用户控制的轻量级的线程。

如下面的代码所示,u1.run()属于方法调用,启动的是主线程main。u1.start()启动的是子线程,Thread-随机数。

线程的创建方式

1. 继承Thread类

java 复制代码
package com.demo2;

//Thread-整数,这就是子线程的名字
public class UserThread  extends  Thread{

	public void run()
	{
	
		System.out.println(Thread.currentThread().getName()+",run");
		
	}
}
java 复制代码
package com.demo2;

public class Test {
	
	public static void main(String[] args) {
		
       System.out.println(Thread.currentThread().getName()+",main函数");
       
		UserThread  u1  = new UserThread();
		u1.start();

	}

}

运行结果:

**注意:**一个线程启动以后,这个线程就不能再次启动了,这个线程已死亡。如果再次启动,这个线程会抛出线程状态异常。

2. 实现Runnable接口

Runnable接口是Thread类的父类,所以对于实现Runnable和继承Thread类来创建线程,实现Runnable比继承Thread更好,可以更好的扩展。

java 复制代码
package com.demo3;

/**
 * Runnable接口是Thread类的父类
 */
public class UserRunnable   implements Runnable{

	public void run() {
		// TODO Auto-generated method stub
		System.out.println(Thread.currentThread().getName()+",run");
	}

}
java 复制代码
package com.demo3;

public class Test {
	
	public static void main(String[] args) {
		
		UserRunnable  ur =  new UserRunnable();
	
		//把这个实现了Runnable接口的对象,构建一个线程对象
		Thread  r1  = new Thread(ur);
		
		r1.start();
	}

}

运行结果:

3.继承TimerTask,定时线程

java 复制代码
package com.demo4;

import java.util.Date;
import java.util.TimerTask;

//定时线程
public class UserTask extends TimerTask {

	@Override
	public void run() {
		// TODO Auto-generated method stub
		System.out.println(Thread.currentThread().getName()+", run"+new Date());
	}

}
java 复制代码
package com.demo4;

import java.util.Timer;

public class Test {

	public static void main(String[] args) {

		// 定时线程的启动有特殊的方法

		UserTask ut = new UserTask();

		// 继承TimerTask不用这个方法,它是一个定时线程
//		Thread  t  = new Thread(ut);
//		t.start();
		
		
		// 建立一个定时器对象
		Timer  t =  new Timer();
		// 安排定时任务执行
		t.schedule(ut,1000,4000);
		
	}

}

t.schedule(ut, 1000, 4000) 这三个参数的意思是:

  • ut - 要执行的任务(必须是 TimerTask 的子类)
  • 1000 - 首次执行的延迟时间(毫秒) = 1秒后开始第一次执行
  • 4000 - 后续执行的间隔时间(毫秒) = 之后每4秒执行一次

运行结果:

4.带有返回值的线程,Callable

下面的代码演示了如何使用 CallableFuture 接口来实现有返回值的多线程任务 。与普通的Runnable不同,Callable可以返回执行结果和抛出异常。

执行流程:

  • 创建线程池Executors.newSingleThreadExecutor()
  • 创建任务new UserCall()
  • 提交任务es.submit(uc) 返回Future对象
  • 获取结果result.get() 阻塞等待任务完成
  • 关闭线程池es.shutdown()
java 复制代码
package com.demo7;

import java.util.concurrent.Callable;

public class UserCall  implements  Callable<Integer>{

	  // Callable的call方法可以有返回值和抛出异常
	public Integer call() throws Exception {
		// TODO Auto-generated method stub
		System.out.println(Thread.currentThread().getName()+",call方法");
		return 10;
	}

}
java 复制代码
package com.demo7;


import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

public class Test {
	
	public static void main(String[] args) {
		
		// 创建单线程的线程池
		ExecutorService  es = 	Executors.newSingleThreadExecutor();
		
		// 创建Callable任务实例
		UserCall  uc = new UserCall();
		
		// 提交任务到线程池,返回Future对象
		Future<Integer>  result = es.submit(uc);
		
		try {
			// 获取任务执行结果(会阻塞直到任务完成)
			System.out.println("返回值:"+result.get());
			
			// 关闭线程池
			es.shutdown();
			
			
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (ExecutionException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
	}

}

运行结果:

5.线程池 ExcuterService

下面的代码演示了如何使用 Java线程池 来执行一个实现了 Runnable 接口的任务。它创建了一个单线程的线程池,然后在这个线程中执行循环打印任务。

java 复制代码
package com.demo8;

public class UserRun1  implements Runnable{

	public void run() {
		// TODO Auto-generated method stub
		for(int i=0;i<5;i++)
		{
			System.out.println(Thread.currentThread().getName()+","+i);
		}
	}

}
java 复制代码
package com.demo8;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class Test {
	
	public static void main(String[] args) {
		
		// 创建单线程的线程池
		ExecutorService  es = Executors.newSingleThreadExecutor();
	
		// 提交Runnable任务到线程池执行
		es.execute(new UserRun1());
		
		// 关闭线程池(不再接受新任务)
		es.shutdown();
	}

}

Executors.newSingleThreadExecutor():

  • 创建只有一个线程的线程池
  • 任务会按提交顺序依次执行
  • 线程会一直存在,可重复使用

execute() vs submit():

java 复制代码
// execute() - 用于Runnable,无返回值
es.execute(runnableTask);

// submit() - 可用于Runnable和Callable,返回Future对象
Future<?> future = es.submit(runnableTask);

运行结果:

线程的生命周期

  1. 创建线程对象

2.线程进入可运行状态 ,可以运行,JVM来调度执行

  1. 进入到运行状态

  2. 对线程的调度(沉睡,让步,合并,线程同步机制,线程通信机制,JUC线程机制)

5.死亡

对线程的调度

沉睡-Thread.sleep()

让当前正在运行的线程睡眠,当睡眠时间到,线程再次进入可运行状态,再次执行还是由JVM调度。

java 复制代码
package com.thread1;

public class UserThread  extends Thread {
	
	public void  run()
	{
		System.out.println(Thread.currentThread().getName()+",线程执行run方法开始");
		
		try {
			//Thread表示当前线程
			//让当前正在运行的线程睡眠
			//睡眠时间到,线程再次进入可运行状态,再次执行还是由JVM调度
			Thread.sleep(6*1000);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		System.out.println(Thread.currentThread().getName()+",线程执行run方法之后");
	
	}

}
java 复制代码
package com.thread1;


public class Test {
	
	public static void main(String[] args) {
		
		for(int i=0;i<5;i++)
		{
			UserThread u1 = new UserThread();
			u1.start();
			
		}
	}

}

运行结果:

让步-Thread.yeild()

当前的线程进行让步,即让出执行权,可能选择让或不让。

java 复制代码
package com.thread2;

public class UserThread   extends Thread{
	
	public void run()
	{
		System.out.println("A");
		
		//让步,让出执行权,可能选择让或不让
 
		 Thread.yield(); 
		 
		System.out.println("B");
		
		//AABB或ABAB
	}

}
java 复制代码
package com.thread2;;

public class Test {
	
	public static void main(String[] args) {
		
		UserThread  u1  = new UserThread();
		UserThread  u2  = new UserThread();
		
		u1.start();
		u2.start();
	}

}

运行结果:

合并-Thread.join()

合并线程去执行。

java 复制代码
package com.thread3;

public class UserThread  extends Thread{
	
	int sum =0;
	
	public void run()
	{
		
		for(int i=0;i<=100;i++)
		{
			
			sum += i; 
			
		}

	}
	
	public int  getSum()
	{
		return this.sum;
	}
	

}
java 复制代码
package com.thread3;

public class Test {
	
	public static void main(String[] args) {
		
		UserThread  u1  = new UserThread();
		u1.start();
		
		try {
			//主线程和子线程的生命周期是隔离的
			//合并到主线程执行
			u1.join();
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		System.out.println("得到子线程的值为:"+u1.getSum());
		
		
		
	}

}

运行结果:

线程的优先级

线程的优先级取值1..10,但是不能够绝对保证优先级高的线程最先启动,只是在一段时候内,最先运行的概率高一点。

java 复制代码
package com.demo10;

public class UserThread   extends Thread{
	
	public void  run()
	{
		System.out.println(Thread.currentThread().getName()+",run...");
	}

}
java 复制代码
package com.demo10;

public class Test {
	
	public static void main(String[] args) {
		
		UserThread  u1 = new UserThread();
		UserThread  u2 = new UserThread();
		UserThread  u3 = new UserThread();
		
		//线程的优先级取值1..10,但是不能够绝对保证优先级高的线程最先启动
		//在一段时候内,最先运行的概率高一点
		u3.setPriority(Thread.MAX_PRIORITY);
		u1.setPriority(Thread.MIN_PRIORITY);
		
		u1.start();
		u2.start();
		u3.start();
	}
	
}

运行结果:

相关推荐
huimingBall3 小时前
确定软件需求的方法
java·大数据·elasticsearch·搜索引擎·需求分析·j#
七夜zippoe3 小时前
Java 技术支撑 AI 系统落地:从模型部署到安全合规的企业级解决方案(四)
java·人工智能·安全
黄昏恋慕黎明3 小时前
0基础了解 java 位图 过滤器 海量数据处理
java·开发语言
MSTcheng.3 小时前
【C++】C++入门—(中)
开发语言·c++
期待のcode3 小时前
SpringMVC的请求接收与结果响应
java·后端·spring·mvc
行走的码农霖悦3 小时前
PHP如何解决使用国密SM4解密Base64数据错误问题?(基于lpilp/guomi)
开发语言·php
CHEN5_026 小时前
【CouponHub开发记录】SpringAop和分布式锁进行自定义注解实现防止重复提交
java·分布式·spring·项目
编啊编程啊程6 小时前
Netty从0到1系列之Selector
java·spring boot·spring cloud·java-ee·kafka·maven·nio
wheeldown6 小时前
【Linux】为什么死循环卡不死 Linux?3 个核心逻辑看懂进程优先级与 CPU 调度密码
linux·运维·服务器·开发语言·c++·unix·进程