Java线程常用的操作方法

目标:

了解设置和取得线程的名称。

了解线程的强制运行。

了解线程的休眠。

了解线程的礼让。

了解线程的中断操作。

具体内容:在多线程中所有的操作方法实际上都是从Thread类开始的。所有的操作都是在Thread类之中的。

线程操作的主要方法

NO	方法名称	类型	描述
1	public Thread(Runnable   target)	构造	接收Runnable接口子类对象,实例化Thread对象
2	public Thread(Runnable target,String  name)	构造	接收Runnable接口子类对象,实例化Thread对象,并设置线程名称
3	public Thread(String  name)	构造	实例化Thread对象,并设置线程名称。
4	public static Thread currentThread()	普通	返回目前正在执行的线程。
5	public final String getName()	普通	返回线程的名称
6	public final int getPriority()	普通	返回线程的优先级
7	public boolean isInterrupted()	普通	判断目前线程是否被中断,如果是,返回true,否则返回false
8	public final boolean isActive()	普通	判断线程是否在活动,如果是返回true,否则返回false
9	public final void join() throws InterruptedException	普通	等待线程死亡
10	public final synchronized void join(long millis) throws
InterruptedException 	普通	等待millis毫秒后,线程死亡。
11	public void run()	普通	执行线程
12	public  final  void setName()	普通	设定线程名称
13	public final void  setPriority(int newPriority)	普通	设定线程的优先级
14	public static void sleep(long millis) throws
InterruptedException	普通	使目前正在执行的线程休眠millis毫秒
15	public void start()	普通	开始执行线程。
16	public static void yield()	普通	将目前正在执行的线程暂停一次,允许其他线程执行
17	public final void setDaemon(boolean on)	普通	将一个线程设置成后台运行
18	public final void setPriority(int   newPriority)	普通	更改线程的优先级

线程名称

取得和设置线程名称

在Thread类中,可以通过getName()方法取得线程名称,通过setName()方法设置线程的名称。

线程的名称一般在启动线程前设置,但也允许为已经存在的线程设置名称。允许两个Thread对象有相同的名字,但为了清晰,应该尽量避免这种情况的发生。

另外,如果程序并没有为线程指定名称,则系统会自动的为线程分配一个名称。

线程的名称最好在线程启动前设置,避免重名。

class MyThread implements Runnable{	// 实现Runnable接口
	public void run(){	// 覆写run()方法
		for(int i=0;i<3;i++){
			System.out.println(Thread.currentThread().getName()
					+ "运行,i = " + i) ;	// 取得当前线程的名字
		}
	}
};
public class ThreadNameDemo{
	public static void main(String args[]){
		MyThread mt = new MyThread() ;	// 实例化Runnable子类对象
		new Thread(mt).start() ;		// 系统自动设置线程名称
		new Thread(mt,"线程-A").start() ;		// 手工设置线程名称
		new Thread(mt,"线程-B").start() ;		// 手工设置线程名称
		new Thread(mt).start() ;		// 系统自动设置线程名称
		new Thread(mt).start() ;		// 系统自动设置线程名称
	}
};

从执行效果来看,指定的名称会自动出现,如果没有指定会发现线程使用自动编号的方式完成,按照:Thread-0、Thread-1 依次编号,实际上肯定在类中存在一个static属性,用于记录编号。

取得当前线程

程序可以通过currentThread()方法取得当前正在运行的线程对象。

class MyThread implements Runnable{	// 实现Runnable接口
	public void run(){	// 覆写run()方法
		for(int i=0;i<3;i++){
			System.out.println(Thread.currentThread().getName()
					+ "运行,i = " + i) ;	// 取得当前线程的名字
		}
	}
};
public class CurrentThreadDemo{
	public static void main(String args[]){
		MyThread mt = new MyThread() ;	// 实例化Runnable子类对象
		new Thread(mt,"线程").start() ;		// 启动线程
		mt.run() ;	// 直接调用run()方法
	}
};

此时发现,程序中由主方法直接通过线程对象调用里面的run()方法,所以输出的结果中包含了一个“main”,此线程就是“mt.run”, 因为调用此语句是由主方法完成的,也就是说实际上主方法本身也是一个线程——主线程。

问题:既然主方法都是以线程的形式出现的,那么Java运行时到底启动了多少个线程?

回答:至少启动了两个。从目前的知识上看,每当Java程序执行的时候,实际上都会启动一个JVM,每一个JVM实际上就是在操作系统中启动了一个进程。Java中本身具备了垃圾收集机制,所以Java运行时至少启动两个线程:主线程、GC。

判断线程是否启动

class MyThread implements Runnable{	// 实现Runnable接口
	public void run(){	// 覆写run()方法
		for(int i=0;i<3;i++){
			System.out.println(Thread.currentThread().getName()
					+ "运行,i = " + i) ;	// 取得当前线程的名字
		}
	}
};
public class ThreadAliveDemo{
	public static void main(String args[]){
		MyThread mt = new MyThread() ;	// 实例化Runnable子类对象
		Thread t = new Thread(mt,"线程");		// 实例化Thread对象
		System.out.println("线程开始执行之前 --> " + t.isAlive()) ;	 // 判断是否启动
		t.start() ;	// 启动线程
		System.out.println("线程开始执行之后 --> " + t.isAlive()) ;	 // 判断是否启动
		for(int i=0;i<3;i++){
			System.out.println(" main运行 --> " + i) ;
		}
		// 以下的输出结果不确定
		System.out.println("代码执行之后 --> " + t.isAlive()) ;	 // 判断是否启动

	}
};

      

发现调用start方法之后线程就激活了,如果线程执行任务完毕后就会被关闭。如果没有执行完毕,仍处于激活状态。

线程的强制运行

在线程操作中,可以使用join()方法让一个线程强制运行,线程强制运行期间,其他线程无法运行,必须等待此线程完成之后才可以继续运行。

class MyThread implements Runnable{	// 实现Runnable接口
	public void run(){	// 覆写run()方法
		for(int i=0;i<50;i++){
			System.out.println(Thread.currentThread().getName()
					+ "运行,i = " + i) ;	// 取得当前线程的名字
		}
	}
};
public class ThreadJoinDemo{
	public static void main(String args[]){
		MyThread mt = new MyThread() ;	// 实例化Runnable子类对象
		Thread t = new Thread(mt,"线程");		// 实例化Thread对象
		t.start() ;	// 启动线程
		for(int i=0;i<50;i++){
			if(i>10){
				try{
					t.join() ;	// 线程强制运行
				}catch(InterruptedException e){}
			}
			System.out.println("Main线程运行 --> " + i) ;
		}
	}
};

线程的休眠

在程序中允许一个线程进行暂时的休眠,直接使用Thread.sleep()方法即可。

class MyThread implements Runnable{	// 实现Runnable接口
	public void run(){	// 覆写run()方法
		for(int i=0;i<50;i++){
			try{
					Thread.sleep(500) ;	// 线程休眠
			}catch(InterruptedException e){}
			System.out.println(Thread.currentThread().getName()
					+ "运行,i = " + i) ;	// 取得当前线程的名字
		}
	}
};
public class ThreadSleepDemo{
	public static void main(String args[]){
		MyThread mt = new MyThread() ;	// 实例化Runnable子类对象
		Thread t = new Thread(mt,"线程");		// 实例化Thread对象
		t.start() ;	// 启动线程
	}
};

会发现每隔500毫秒,执行一次。

线程的中断

当一个线程运行的时候,另外一个线程可以直接通过interrupt()方法 中断其运行状态。

class MyThread implements Runnable{	// 实现Runnable接口
	public void run(){	// 覆写run()方法
		System.out.println("1、进入run()方法") ;
		try{
				Thread.sleep(10000) ;	// 线程休眠10秒
				System.out.println("2、已经完成了休眠") ;
		}catch(InterruptedException e){
			System.out.println("3、休眠被终止") ;
			return ; // 返回调用处
		}
		System.out.println("4、run()方法正常结束") ;
	}
};
public class ThreadInterruptDemo{
	public static void main(String args[]){
		MyThread mt = new MyThread() ;	// 实例化Runnable子类对象
		Thread t = new Thread(mt,"线程");		// 实例化Thread对象
		t.start() ;	// 启动线程
		try{
				Thread.sleep(2000) ;	// 线程休眠2秒
		}catch(InterruptedException e){
			System.out.println("3、休眠被终止") ;
		}
		t.interrupt() ;	// 中断线程执行
	}
};

后台进程

在Java中,只要有一个程序没有执行完(一个线程在运行),则整个Java的进程就不会消失,所以此时可以设置一个后台线程,这样即使Java进程结束了,此后台线程依然会继续运行,也就是说不影响进程的结束。要想实现这样的操作,直接使用setDaemon()方法即可。

class MyThread implements Runnable{	// 实现Runnable接口
	public void run(){	// 覆写run()方法
		while(true){
			System.out.println(Thread.currentThread().getName() + "在运行。") ;
		}
	}
};
public class ThreadDaemonDemo{
	public static void main(String args[]){
		MyThread mt = new MyThread() ;	// 实例化Runnable子类对象
		Thread t = new Thread(mt,"线程");		// 实例化Thread对象
		t.setDaemon(true) ;	// 此线程在后台运行
		t.start() ;	// 启动线程
	}
};

会发现没有打印任何东西,如果设置为false的话则会一直打印,不会结束进程。

线程的优先级

在Java的线程操作中,所有的线程在运行前都会保持在就绪状态,那么此时哪个线程的优先级高,哪个线程就有可能被先执行。

class MyThread implements Runnable{	// 实现Runnable接口
	public void run(){	// 覆写run()方法
		for(int i=0;i<5;i++){
			try{
					Thread.sleep(500) ;	// 线程休眠
			}catch(InterruptedException e){}
			System.out.println(Thread.currentThread().getName()
					+ "运行,i = " + i) ;	// 取得当前线程的名字
		}
	}
};
public class ThreadPriorityDemo{
	public static void main(String args[]){
		Thread t1 = new Thread(new MyThread(),"线程A") ;	// 实例化线程对象
		Thread t2 = new Thread(new MyThread(),"线程B") ;	// 实例化线程对象
		Thread t3 = new Thread(new MyThread(),"线程C") ;	// 实例化线程对象
		t1.setPriority(Thread.MIN_PRIORITY) ;	// 优先级最低
		t2.setPriority(Thread.MAX_PRIORITY) ;	// 优先级最高
		t3.setPriority(Thread.NORM_PRIORITY) ;	// 优先级居中
		t1.start() ;	// 启动线程
		t2.start() ;	// 启动线程
		t3.start() ;	// 启动线程
	}
};

主线程的优先级是NORM_PRIORITY 为5 是中等级别。

默认的线程优先级也是NORM_PRIORITY。

程序示例如下:

public class MainPriorityDemo{
	public static void main(String args[]){
		System.out.println("主方法的优先级:" +
			Thread.currentThread().getPriority()) ;	// 取得主方法的优先级
		System.out.println("MAX_PRIORITY = " + Thread.MAX_PRIORITY) ;
		System.out.println("NORM_PRIORITY = " + Thread.NORM_PRIORITY) ;
		System.out.println("MIN_PRIORITY = " + Thread.MIN_PRIORITY) ;
	}
};

线程的礼让

在线程操作中,也可以使用yield()方法将一个线程的操作暂时让给其他线程执行。

class MyThread implements Runnable{	// 实现Runnable接口
	public void run(){	// 覆写run()方法
		for(int i=0;i<5;i++){
			try{
				Thread.sleep(500) ;
			}catch(Exception e){}
			System.out.println(Thread.currentThread().getName()
					+ "运行,i = " + i) ;	// 取得当前线程的名字
			if(i==2){
				System.out.print("线程礼让:") ;
				Thread.currentThread().yield() ;	// 线程礼让
			}
		}
	}
};
public class ThreadYieldDemo{
	public static void main(String args[]){
		MyThread my = new MyThread() ;	// 实例化MyThread对象
		Thread t1 = new Thread(my,"线程A") ;
		Thread t2 = new Thread(my,"线程B") ;
		t1.start() ;
		t2.start() ;
	}
};

总结:

重点是掌握线程的操作方法,对于这些操作方法只需要从Thread类中查找即可。

线程操作范例

实例要求:设计一个线程操作类,要求可以产生三个线程对象,并可以分别设置三个线程的休眠时间,如下所示:

线程A,休眠10秒。

线程B,休眠20秒

线程C,休眠30秒

分析:已知线程的实现有两种方式,一种是继承Thread类,另外一种是实现Runnable接口。而且在类中应该保存线程名称和休眠时间两个属性。

(一)使用Thread类

在Thread类中直接存在了name属性。

class MyThread extends Thread{
	private int time ;
	public MyThread(String name,int time){
		super(name) ;	// 设置线程名称
		this.time = time ;	// 设置休眠时间
	}
	public void run(){
		try{
			Thread.sleep(this.time) ;	// 休眠指定的时间
		}catch(InterruptedException e){
			e.printStackTrace() ;
		}
		System.out.println(Thread.currentThread().getName() + "线程,休眠"
			+ this.time + "毫秒。") ;
	}
};
public class ExecDemo01{
	public static void main(String args[]){
		MyThread mt1 = new MyThread("线程A",10000) ;	// 定义线程对象,指定休眠时间
		MyThread mt2 = new MyThread("线程B",20000) ;	// 定义线程对象,指定休眠时间
		MyThread mt3 = new MyThread("线程C",30000) ;	// 定义线程对象,指定休眠时间
		mt1.start() ;	// 启动线程
		mt2.start() ;	// 启动线程
		mt3.start() ;	// 启动线程
	}
};

(二)使用Runnable

如果使用Runnable接口,则类中是没有线程名称存在的,所以应该单独建立一个name属性,以保存线程的名称。

class MyThread implements Runnable{
	private String name ;
	private int time ;
	public MyThread(String name,int time){
		this.name = name ;	// 设置线程名称
		this.time = time ;	// 设置休眠时间
	}
	public void run(){
		try{
			Thread.sleep(this.time) ;	// 休眠指定的时间
		}catch(InterruptedException e){
			e.printStackTrace() ;
		}
		System.out.println(this.name + "线程,休眠"
			+ this.time + "毫秒。") ;
	}
};
public class ExecDemo02{
	public static void main(String args[]){
		MyThread mt1 = new MyThread("线程A",10000) ;	// 定义线程对象,指定休眠时间
		MyThread mt2 = new MyThread("线程B",20000) ;	// 定义线程对象,指定休眠时间
		MyThread mt3 = new MyThread("线程C",30000) ;	// 定义线程对象,指定休眠时间
		new Thread(mt1).start() ;	// 启动线程
		new Thread(mt2).start() ;	// 启动线程
		new Thread(mt3).start() ;	// 启动线程
	}
};

时间: 2024-10-09 23:19:17

Java线程常用的操作方法的相关文章

线程常用的操作方法

1.Thread(Runnable target) 分配新的Thread对象 2.Thread(Runnable target,String name) 分配新的Thread对象 3.Thread(String name) 分配新的Thread对象 4.static Thread currentThread() 返回对当前正在执行的线程对象的引用 5.long getId() 返回该线程的标识符 6.String getName() 返回该线程的名称 7.void setName(String

多线程之线程常用操作方法

在Java实现多线程的程序中,虽然Thread类实现了Runnable接口,但是操作线程的主要方法并不在Runnable接口中,而在Thread类中. 模版 class MyThread implements Runnable{ public void run(){//覆写run方法 for(int i=0;i<3;i++) { System.out.println("SSS"); } ] } public class TestThread{ public static void

线程常用操作方法

在多线程中所有的操作方法都是从Thread类开始的,所有的操作基本上都在Thread类中. 1,线程名称 1,在Thread类中可以通过getName()方法取得线程名称,通过setName()设置线程名称. 2,线程的名称一般在启动线程前设置,但也允许为运行的线程设置名称,允许两个Thread对象有相同名称,但是应该避免. 3,如果程序没有为线程指定名称,系统会自动为线程设置名称. class MyThread implements Runnable{ // 实现Runnable接口 publ

java线程的状态及操作方法

一.线程的状态 1. 新建状态 在程序中用构造方法创建了一个线程对象后,新的线程对象便处于新建状态,此时,它已经有了相应的内存空间和其它资源,但还处于不可运行状态.新建一个线程对象可采用线程构造方法来实现. 例如:Thread thread=new Thread(); 2. 就绪状态 新建线程对象后,调用该线程的start()方法就可以启动线程.当线程启动时,线程进入就绪状态.此时,线程将进入线程队列排队,等待CPU服务,这表明它已经具备了运行条件. 3. 运行状态 当就绪状态的线程被调用并获得

java线程操作方法setName,getName,isAlive

/** * ThreadDemo2.java * @author cjc * */ public class ThreadDemo2 { public static void main(String[] args) { Thread th=new Thread(new TestThread()); th.setName("子线程1"); th.start(); for(int i=0;i<10;i++) { System.out.println("Thread &quo

java线程池与五种常用线程池策略使用与解析

背景:面试中会要求对5中线程池作分析.所以要熟知线程池的运行细节,如CachedThreadPool会引发oom吗? java线程池与五种常用线程池策略使用与解析 可选择的阻塞队列BlockingQueue详解 首先看一下新任务进入时线程池的执行策略: 如果运行的线程少于corePoolSize,则 Executor始终首选添加新的线程,而不进行排队.(如果当前运行的线程小于corePoolSize,则任务根本不会存入queue中,而是直接运行) 如果运行的线程大于等于 corePoolSize

Java中常用的四种线程池

在Java中使用线程池,可以用ThreadPoolExecutor的构造函数直接创建出线程池实例,如何使用参见之前的文章Java线程池构造参数详解.不过,在Executors类中,为我们提供了常用线程池的创建方法.接下来我们就来了解常用的四种: newFixedThreadPool 首先,看一下这种线程池的创建方法: public static ExecutorService newFixedThreadPool(int nThreads) { return new ThreadPoolExec

java线程池和五种常用线程池的策略使用与解析

java线程池和五种常用线程池策略使用与解析 一.线程池 关于为什么要使用线程池久不赘述了,首先看一下java中作为线程池Executor底层实现类的ThredPoolExecutor的构造函数 public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory th

java 线程详解

5月7号  周末看了一下线程方面的内容 ,边看视频边看书还附带着参考了很多人的博客,一天的收获,写下来整理一下:感觉收获还是挺多的:过段时间可能看完java  这几大块要去看一下关于spring boot  的内容顺便  也整理一下:附上我参考的 几本书: 关于java  线程,首先要了解一下线程和进程之间的关系.区别以及他们之间的概念: 首先是线程: 什么是线程? 线程是在程序执行过程中能够执行部分代码的一个执行单元,也看看做是一个轻量级的进程:线程是程序内的程序控制流只能使用程序内分配给程序