线程常用方法

线程池

作用:提高程序的执行效率;
1,如果程序中有大量短时间任务的线程任务,由于创建和销毁线程需要和底层操作系统交互,大量时间都耗费在创建和销毁线程上,因而比较浪费时间,系统效率很低;线程池里的每一个线程任务结束后,并不会死亡,而是再次回到线程池中成为空闲状态,等待下一个对象来使用,因而借助线程池可以提高程序的执行效率。
控制线程的数量,防止程序崩溃;
2,如果不加限制地创建和启动线程很容易造成程序崩溃,比如高并发1000W个线程,JVM就需要有保存1000W个线程的空间,这样极易出现内存溢出;线程池中线程数量是一定的,可以有效避免出现内存溢出。

分析如下代码:

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

public class Text {

	public static void main(String[] args) {
		//线程池:实现。
		ExecutorService service=Executors.newFixedThreadPool(3);//创建3个线程池。
		service.submit(new Timenow("线程1"));//提交事务1
		service.submit(new Timenow("线程2"));//提交事务2
		service.submit(new Timenow("线程3"));//提交事务3,只有三个线程池,所以只会一次执行三个事务。
		service.submit(new Timenow("线程4"));//前三个事务中某一个(因为是抢占式执行,所以不确定那个会先执行完成)执行完毕,才会提交事务4
		service.shutdown();//关闭资源
	}
}

class Timenow implements Runnable{
	String name;
	Timenow (String name){
		this.name=name;
	}

	@Override
	public void run() {
		for(int i=0;i<3;i++) {
			System.out.println(name+";"+new Date());
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		System.out.println("......");
	}
}

关于输出结果:
下边列出可能的一种输出结果,我们看到线程1,2,3抢占式交叉进行,其中的某一个线程结束后,线程4才开始执行。

线程1;Sun Jun 30 11:39:11 CST 2019
线程3;Sun Jun 30 11:39:11 CST 2019
线程2;Sun Jun 30 11:39:11 CST 2019
线程3;Sun Jun 30 11:39:12 CST 2019
线程2;Sun Jun 30 11:39:12 CST 2019
线程1;Sun Jun 30 11:39:12 CST 2019
线程1;Sun Jun 30 11:39:13 CST 2019
线程2;Sun Jun 30 11:39:13 CST 2019
线程3;Sun Jun 30 11:39:13 CST 2019
线程3......
线程2......
线程4;Sun Jun 30 11:39:14 CST 2019
线程1......
线程4;Sun Jun 30 11:39:15 CST 2019
线程4;Sun Jun 30 11:39:16 CST 2019
线程4......

线程常用方法

interrupt()

interrupt方法:结束线程在调用Object类的wait方法或该类的join方法、sleep方法过程中的阻塞状态,并在调用wait、join和sleep方法处产生InterruptedException异常。
看如下例子:

import java.util.Date;

public class T {

	public static void main(String[] args) {//1,main方法为主线程,下边创建一个时间线程。
		Thread thread=new Thread(new Timenew());//2,创建新的时间线程
		thread.start();//3,时间线程准备就绪
		
		try {
			Thread.sleep(5000);//主线程阻塞5秒,下边代码先不执行。
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		
		thread.interrupt();//5,改行代码执行,调用interrupt方法的线程中断阻塞,时间线程中断阻塞。
	}
}

class Timenew implements Runnable{

	@Override
	public void run() {
		System.out.println(new Date());
		try {
			Thread.sleep(30000);//4,时间线程阻塞30秒,此时主线程和时间线程都阻塞,主线程先中断阻塞。
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.err.println("......");//6,时间线程提前中断阻塞。
	}
}

输出如下结果:
在这里插入图片描述

currentThread()

返回当前正在执行的线程对象。

public class T {
	public static void main(String[] args) {
		
		Thread thread=Thread.currentThread();//返回当前线程:此处只有主线程在执行,所以返回主线程。
		System.out.println("主线程"+thread);
		
		Thread thread1=new Thread(new Timenew());//创建新的时间线程
		thread1.start();
		System.out.println("时间线程"+thread1);//输出时间线程
	}
}

class Timenew implements Runnable{

	@Override
	public void run() {
		Thread t=Thread.currentThread();//时间线程开始执行
		System.out.println("时间线程"+t);
	}
}

输出结果如下:
在这里插入图片描述

isAlive()

判定该线程是否处于就绪、运行或阻塞状态,如果是则返回true,否则返回false。

public class T {

	public static void main(String[] args) {
		Thread thread =Thread.currentThread();//主线程
		System.out.println("1..."+thread.isAlive());//判断主线程是否在执行,一定输出true
		TimeThread1 timeThread=new TimeThread1(thread);//thread为主线程对象
		timeThread.start();
		System.out.println(111);
	}
}

class TimeThread1 extends Thread{

	Thread thread;

	public TimeThread1(Thread thread) {
		this.thread=thread;
	}
	
	@Override
	public void run() {
		System.out.println("2..."+thread.isAlive());//如果先执行111,此行代码很大可能输出false,因为主线程很大可能结束了。
		try {
			Thread.sleep(20);//在时间线程阻塞的时候,主线程一定会执行完毕,所以下边代码一定输出false
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.out.println("3..."+thread.isAlive());//此处一定输出false
	}
}

输出结果如下:
在这里插入图片描述

setDaemon()

看如下例子:

public class T {

	public static void main(String[] args) {
		TimeThread1 timeThread=new TimeThread1();//时间线程
		timeThread.setDaemon(true);//时间线程设为守护线程。守护线程会随着进程中最后一个非守护线程的结束而结束。
		timeThread.start();//该行代码结束,主线程可能立马结束,不会输出111.如果主线程没有结束,会输出111.再结束主线程。
	}
}

class TimeThread1 extends Thread{

	@Override
	public void run() {
		while (true) {
			System.out.println(111);
		}
	}
}

输出某个结果为:
在这里插入图片描述
再看如下代码:

public class T {

	public static void main(String[] args) {
		TimeThread1 timeThread=new TimeThread1();//时间线程
		timeThread.setDaemon(true);//时间线程设为守护线程。守护线程会随着进程中最后一个非守护线程的结束而结束。
		timeThread.start();//该行代码结束,主线程可能立马结束,不会输出111.如果主线程没有结束,会输出111.再结束主线程。
		
		try {
			Thread.sleep(3000);//加该行代码后,主线程阻塞,阻塞期间时间线程一定会执行,一定输出111,并且三秒之后结束线程,因为主线程为非守护线程,主线程结束后,守护线程也结束。
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
}

class TimeThread1 extends Thread{

	@Override
	public void run() {
		while (true) {
			System.out.println(111);
		}
	}
}

在主线程阻塞期间,一定会输出111,最后主线程结束,守护线程也结束。

join()

执行该方法的线程进入阻塞状态,直到调用该方法的线程结束后再由阻塞转为就绪状态。
如下例子:

import java.util.Date;

public class T {

	public static void main(String[] args) {
		TimeThread1 timeThread=new TimeThread1();
		timeThread.start();//就绪状态:开始执行线程中代码。
		
		CountThread countThread=new CountThread(timeThread);//紧接着开启另一个线程。不会是一个线程结束再开启另一个线程。
		countThread.start();//就绪状态:开始执行代码。
	}
}

class CountThread extends Thread{

	TimeThread1 timeThread;
	public CountThread(TimeThread1 timeThread) {//构造方法
		this.timeThread=timeThread;
	}
	
	@Override
	public void run() {
		for(int i=0;i<5;i++) {
			System.out.println(i);
			try {
				timeThread.join();//一个线程执行另一个线程调用join方法的代码,则该计数器线程阻塞,一直到调用join方法的线程结束。
			} catch (InterruptedException e1) {
				e1.printStackTrace();
			}
			
			try {
				sleep(1000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		
	}
}

class TimeThread1 extends Thread{

	@Override
	public void run() {
		for(int i=0;i<5;i++) {
			System.out.println(new Date());
			try {
				sleep(1000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
}

输出结果分析:计数器线程会在某一时刻阻塞,只要时间线程开始执行,就会有一直执行该时间线程。
在这里插入图片描述
此种情况下,计数器线程执行了一次后阻塞,时间线程只要开始加入,就会一直执行该时间线程。

其他方法

void start():使该线程开始启动,Java 虚拟机负责调用该线程的 run() 方法。多次启动一个线程是非法的。
void sleep(long millis):Thread类静态方法,线程进入阻塞状态,在指定时间(单位为毫秒)到达之后进入就绪状态(Runnable),而非立即进入执行状态。
void yield():静态方法,当前线程放弃占用CPU资源,回到就绪状态,使其他优先级不低于此线程的线程有机会被执行。
void setPriority(int newPriority):设置当前线程的优先级,线程优先级越高,线程获得执行的次数越多,Java线程的优先级用整数表示,取值范围是1~10,Thread类有以下三个静态常量:
static int MAX_PRIORITY 最高优先级值为10;
static int NORM_PRIORITY 默认优先级值为5;
static int MIN_PRIORITY 最低优先级值为1;
注意:同一个线程类创建的多个线程,线程优先级越高的线程获得的执行次数极有可能越多;但是不同线程类创建的线程,线程优先级越高,执行次数不一定越多,这个run方法的代码复杂度有关!
int getPriority():获得当前线程的优先级。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值