线程常用操作方法

时间:2022-07-05 14:37:55

在多线程中所有的操作方法都是从Thread类开始的,所有的操作基本上都在Thread类中。

 线程常用操作方法

1,线程名称

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

  2,线程的名称一般在启动线程前设置,但也允许为运行的线程设置名称,允许两个Thread对象有相同名称,但是应该避免。

  3,如果程序没有为线程指定名称,系统会自动为线程设置名称。

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() ; // 系统自动设置线程名称
}
};

 

currentThread(),获取当前线程。

 运行结果:

线程-A运行,i = 0
线程
-B运行,i = 0
Thread
-1运行,i = 0
Thread
-0运行,i = 0
Thread
-0运行,i = 1
Thread
-0运行,i = 2
Thread
-1运行,i = 1
线程
-B运行,i = 1
Thread
-2运行,i = 0
线程
-A运行,i = 1
Thread
-2运行,i = 1
线程
-B运行,i = 2
Thread
-1运行,i = 2
Thread
-2运行,i = 2
线程
-A运行,i = 2

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

2,当前线程:CurrentThread()

  程序可以通过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()方法
}
};

  运行结果:

main运行,i = 0
线程运行,i
= 0
main运行,i = 1

线程运行,i
= 1
main运行,i = 2

线程运行,i
= 2

  此时发现,程序中由主方法直接通过线程对象调用里面的run()方法,所有此时的结果包含一个"main",此线程就是由“mt.run()”产生的,因为调用此语句是由主方法完成的。

也就是说,主方法本身也是一个线程---主线程

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

  回答:至少启动了两个。

    从之前学习的情况来看,每当JAVA执行,都会启动一个JVM,每一个JVM都是在操作系统中启动一个线程。

    JAVA本身有垃圾回收机制,所以至少启动了两个线程:主线程,GC。

3,判断线程是否在执行:isAlive

  

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()) ; // 判断是否启动

}
};

  运行结果:

线程开始执行之前 --> false
线程开始执行之后
--> true
main运行
--> 0
main运行
--> 1
main运行
--> 2
线程运行,i
= 0
代码执行之后
--> true
线程运行,i
= 1
线程运行,i
= 2

4,线程强制运行:join()

  可以通过join()方法使得一个线程强制运行,线程强制运行期间,其他线程无法运行,必须等待此线程完成之后,才可以继续运行

package Thread1;
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 demo1{
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) ;
}
}
};

运行结果:

线程运行,i = 0
Main线程运行
--> 0
线程运行,i
= 1
Main线程运行
--> 1
线程运行,i
= 2
Main线程运行
--> 2
线程运行,i
= 3
线程运行,i
= 4
线程运行,i
= 5
线程运行,i
= 6
线程运行,i
= 7
线程运行,i
= 8
线程运行,i
= 9
Main线程运行
--> 3
线程运行,i
= 10
Main线程运行
--> 4
线程运行,i
= 11
线程运行,i
= 12
线程运行,i
= 13
Main线程运行
--> 5
线程运行,i
= 14
Main线程运行
--> 6
线程运行,i
= 15
线程运行,i
= 16
线程运行,i
= 17
线程运行,i
= 18
线程运行,i
= 19
Main线程运行
--> 7
线程运行,i
= 20
Main线程运行
--> 8
线程运行,i
= 21
Main线程运行
--> 9
线程运行,i
= 22
Main线程运行
--> 10
线程运行,i
= 23
线程运行,i
= 24
线程运行,i
= 25
线程运行,i
= 26
线程运行,i
= 27
线程运行,i
= 28
线程运行,i
= 29
线程运行,i
= 30
线程运行,i
= 31
线程运行,i
= 32
线程运行,i
= 33
线程运行,i
= 34
线程运行,i
= 35
线程运行,i
= 36
线程运行,i
= 37
线程运行,i
= 38
线程运行,i
= 39
线程运行,i
= 40
线程运行,i
= 41
线程运行,i
= 42
线程运行,i
= 43
线程运行,i
= 44
线程运行,i
= 45
线程运行,i
= 46
线程运行,i
= 47
线程运行,i
= 48
线程运行,i
= 49
Main线程运行
--> 11
Main线程运行
--> 12
Main线程运行
--> 13
Main线程运行
--> 14
Main线程运行
--> 15
Main线程运行
--> 16
Main线程运行
--> 17
Main线程运行
--> 18
Main线程运行
--> 19
Main线程运行
--> 20
Main线程运行
--> 21
Main线程运行
--> 22
Main线程运行
--> 23
Main线程运行
--> 24
Main线程运行
--> 25
Main线程运行
--> 26
Main线程运行
--> 27
Main线程运行
--> 28
Main线程运行
--> 29
Main线程运行
--> 30
Main线程运行
--> 31
Main线程运行
--> 32
Main线程运行
--> 33
Main线程运行
--> 34
Main线程运行
--> 35
Main线程运行
--> 36
Main线程运行
--> 37
Main线程运行
--> 38
Main线程运行
--> 39
Main线程运行
--> 40
Main线程运行
--> 41
Main线程运行
--> 42
Main线程运行
--> 43
Main线程运行
--> 44
Main线程运行
--> 45
Main线程运行
--> 46
Main线程运行
--> 47
Main线程运行
--> 48
Main线程运行
--> 49

3.5  线程的休眠

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

  sleep定义格式:

public static void sleep(long milis,int nanos)
throws InterruptedException

  首先,static,说明可以由Thread类名称调用,其次throws表示如果有异常要在调用此方法处处理异常

所以sleep()方法要有InterruptedException 异常处理,而且sleep()调用方法通常为Thread.sleep(500) ;形式

  例子:

package Thread1;
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 demo1{
public static void main(String args[]){
MyThread mt
= new MyThread() ; // 实例化Runnable子类对象
Thread t = new Thread(mt,"线程"); // 实例化Thread对象
t.start() ; // 启动线程
}
};

会发现运行过程中,线程名是一个个间隔一定时间出来的,这里达到了休眠效果。

线程运行,i = 0
线程运行,i
= 1
线程运行,i
= 2
线程运行,i
= 3
线程运行,i
= 4
线程运行,i
= 5
线程运行,i
= 6
线程运行,i
= 7
线程运行,i
= 8
线程运行,i
= 9
线程运行,i
= 10
线程运行,i
= 11
线程运行,i
= 12
线程运行,i
= 13
线程运行,i
= 14
线程运行,i
= 15
线程运行,i
= 16
线程运行,i
= 17
线程运行,i
= 18
线程运行,i
= 19
线程运行,i
= 20
线程运行,i
= 21
线程运行,i
= 22
线程运行,i
= 23
线程运行,i
= 24
线程运行,i
= 25
线程运行,i
= 26
线程运行,i
= 27
线程运行,i
= 28
线程运行,i
= 29
线程运行,i
= 30
线程运行,i
= 31
线程运行,i
= 32
线程运行,i
= 33
线程运行,i
= 34
线程运行,i
= 35
线程运行,i
= 36
线程运行,i
= 37
线程运行,i
= 38
线程运行,i
= 39
线程运行,i
= 40
线程运行,i
= 41
线程运行,i
= 42
线程运行,i
= 43
线程运行,i
= 44
线程运行,i
= 45
线程运行,i
= 46
线程运行,i
= 47
线程运行,i
= 48
线程运行,i
= 49

3.6 线程的中断

  一个线程可以被另一个线程中断其操作的状态,使用 interrupt()方法完成。

package Thread1;
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、休眠被终止") ;
}
System.out.println(
"4、run()方法正常结束") ;
}
};
public class demo1{
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() ;
// 中断线程执行
}
};

运行结果:

1、进入run()方法
3、休眠被终止
4、run()方法正常结束

  会看到,在1到3的时候会因为线程休眠2秒而卡顿了一下。

  但是,既然线程中断了,那么4,这句话不应该打出来的,因此要在3,线程被终止处添加一句话rutrun,表示返回调用处

package Thread1;
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 demo1{
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() ;
// 中断线程执行
}
};

运行结果:

1、进入run()方法
3、休眠被终止

3.7 后台线程

  在Java中,只要一个线程没有执行完(一个线程在运行),则整个Java的进程不会消失,所以此时可以设置一个后台线程,这样即使java线程结束了,则后台线程

依旧会继续执行。要想实现这个操作,要使用setDaemon()方法完成。

   t.setDaemon(true) ; 

class MyThread implements Runnable{    // 实现Runnable接口
public void run(){ // 覆写run()方法
     int i=0; while(true){    //设置死循环,这样来实现线程不断运行,设置后台运行。
System.out.println(Thread.currentThread().getName()
+ "在运行。"+i) ;
}
}
};
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() ; // 启动线程
}
};

3.8线程的优先级

  获取优先级的方法:getPriority();

  优先级分为最低,最高,普通三个(Thread.MIN_PRIORITY,Thread.MAX_PRIORITY,Thread.NORM_PRIORITY),

设置优先级:

MyThread  t1=new MyThread();
Thread t3
= new Thread(t1,"线程C") ;//实例化线程对象
t3.setPriority(Thread.MIN_PRIORITY) ;//设置优先级为最低

例子:

package Thread1;
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 demo1{
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() ; // 启动线程
}
};

运行结果:

线程B运行,i = 0
线程C运行,i
= 0
线程A运行,i
= 0
线程B运行,i
= 1
线程C运行,i
= 1
线程A运行,i
= 1
线程B运行,i
= 2
线程A运行,i
= 2
线程C运行,i
= 2
线程B运行,i
= 3
线程C运行,i
= 3
线程A运行,i
= 3
线程B运行,i
= 4
线程C运行,i
= 4
线程A运行,i
= 4

主方法的优先级

  主方法的优先级是NORM_PRIORITY.

package Thread1;
public class demo1{
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) ;
}
};

运行结果:

主方法的优先级:5
MAX_PRIORITY
= 10
NORM_PRIORITY
= 5
MIN_PRIORITY
= 1

  由此可知,主方法优先级是5,也就是普通优先级,而且主方法是一个线程对象。

3.9 线程的礼让

  yield()方法实现线程的礼让。

package Thread1;
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 demo1{
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() ;
}
};

运行结果:

线程A运行,i = 0
线程B运行,i
= 0
线程B运行,i
= 1
线程A运行,i
= 1
线程A运行,i
= 2
线程礼让:线程B运行,i
= 2
线程礼让:线程A运行,i
= 3
线程B运行,i
= 3
线程A运行,i
= 4
线程B运行,i
= 4