一.线程概述

1.进程和线程的概念

进程:进程是操作系统结构的基础;是一次程序的执行;是一个程序及其数据在处理机上顺序执行时所发生的活动;是程序在一个数据集合上运行的过程,它是系统进行资源分配和调度的一个独立单位;进程是受操作系统管理的基本运行单元。

线程:可以理解成是在进程中独立运行的子任务;使用多线程也就是在使用异步。线程分为两种一种是用户线程,一种是守护线程;守护线程是一种特殊的线程,当进程中不存在非守护线程了,则守护线程自动销毁(垃圾回收线程),setDaemon(true)设置线程为守护线程。

2.创建线程的方式

  • 继承Thread类
package chapter1.create;

public class MyThread extends Thread{
	
	@Override
	public void run() {
		super.run();
		System.out.println("MyThread");
	}

}
package chapter1.create;

public class Run {
    
    public static void main(String[] args) {
        MyThread myThread = new MyThread();
        myThread.start();
        System.out.println("end!");
    }

}

运行结果如下:

end!
MyThread

线程是一个子任务,CUP以不确定的方式,或者说是随机的时间来调用线程中的run方法,所以就会出现先打印end!,再打印MyThread了。

  • 实现Runnable接口
package chapter1.create;

public class MyRunnable implements Runnable{

	@Override
	public void run() {
		System.out.println("运行中...");
	}

}
package chapter1.create;

public class Run {
	
	public static void main(String[] args) {
		MyRunnable myRunnable = new MyRunnable();
		Thread thread = new Thread(myRunnable);
		thread.start();
		System.out.println("运行结束");
	}

}

 运行结果:

运行结束
运行中...
Thread.java类也实现了Runnable接口,也就意味着Thread(myRunnable)可以传入一个Thread类的对象,这样做可以将一个Thread对象中的run方法交由其他的线程进行调用。

使用继承Thread类的方式创建线程时,最大的局限就是不支持多继承。

3.常用方法介绍

  • currentThread()方法可返回代码段正在被哪个线程调用的信息。
package chapter1.create;

public class MehthodCurrentThreadTest {
   
    static class CountOperate extends Thread{
        public CountOperate() {
            System.out.println("CountOperate init----begin");
            System.out.println("Thread.currentThread().getName()="+Thread.currentThread().getName());
            System.out.println("this.getName()="+this.getName());
            System.out.println("CountOperate init----end");
        }
        
        @Override
        public void run() {
            super.run();
            System.out.println("run----begin");
            System.out.println("Thread.currentThread().getName()="+Thread.currentThread().getName());
            System.out.println("this.getName()="+this.getName());
            System.out.println("run----end");
        }
    }
    
    public static void main(String[] args) {
        CountOperate countOperate = new CountOperate();
        Thread t = new Thread(countOperate);
        t.setName("A");
        t.start();
    }
}

运行结果:

CountOperate init----begin
Thread.currentThread().getName()=main
this.getName()=Thread-0
CountOperate init----end
run----begin
Thread.currentThread().getName()=A
this.getName()=Thread-0
run----end

  • isAlive()判断当前的线程是否处于活动状态,活动状态就是线程已经启动且尚未终止。
  • sleep()是在指定的毫秒数内让当前"正在执行的线程"休眠(暂停执行),这个"正在执行的线程"是指this.currentThread()返回的线程。
  • getId()取得线程的唯一标识。
  • yield()方法的作用是放弃当前的CPU资源,将它让给其他的任务去占用CPU执行时间。但放弃的时间不确定,有可能刚刚放弃,马上有获得CPU时间片。
  • suspend():暂停,已废弃。会有独占和不同步的问题。
  • resume():恢复,已废弃;会有独占和不同步的问题。

 4.停止线程

判断线程是否为中断状态的方法:

  • interrupted():当前线程是否已经是中断状态,当前线程指运行interrupted()方法的线程,执行后具有将状态标志清除为false的功能;
    • public static boolean interrupted() {
            return currentThread().isInterrupted(true);
      }
  • isInterrupted():线程对象是否已经是中断状态,但不清除状态标志。

停止线程的方法:

  • 使用interrupt方法中断线程,但方法并没有停止线程,只是将状态标志为中断,调用isInterrupted()将返回true。
package chapter1.create.threadinterrupt;

public class MyThread extends Thread{
	
	@Override
	public void run() {
		super.run();
		for(int i=0;i<500000;i++) {
			System.out.println("i="+(i+1)+"interrupted------------"+this.isInterrupted());
		}
	}

}
package chapter1.create.threadinterrupt;

public class Run {
	
	public static void main(String[] args) {
		try {
			MyThread myThread = new MyThread();
			myThread.start();
			Thread.sleep(2000);
			myThread.interrupt();
		} catch (Exception e) {
			System.out.println("main catch.");
			e.printStackTrace();
		}
	}

}

 运行结果:

i=499992interrupted------------true
i=499993interrupted------------true
i=499994interrupted------------true
i=499995interrupted------------true
i=499996interrupted------------true
i=499997interrupted------------true
i=499998interrupted------------true
i=499999interrupted------------true
i=500000interrupted------------true

在沉睡中停止:

package chapter1.create.threadinterrupt;

public class StopWhenSleepTest {

static class MyThread extends Thread{
		
		@Override
		public void run() {
			super.run();
			try {
				System.out.println("run begin");
				Thread.sleep(200000);
				System.out.println("run end");
			} catch (InterruptedException e) {
				System.out.println("进MyThread.java类run方法中的catch了。"+this.isInterrupted());
				e.printStackTrace();
			}
		}
	}
	
	public static void main(String[] args) {
		try {
			MyThread myThread = new MyThread();
			myThread.start();
			Thread.sleep(2000);
			myThread.interrupt();
		} catch (Exception e) {
			System.out.println("main catch.");
			e.printStackTrace();
		}
		System.out.println("Main end");
	}
}

 运行结果:

run begin
Main end
进MyThread.java类run方法中的catch了。false
java.lang.InterruptedException: sleep interrupted
    at java.lang.Thread.sleep(Native Method)
    at chapter1.create.threadinterrupt.StopWhenSleepTest$MyThread.run(StopWhenSleepTest.java:12)

如果在sleep状态下停止线程,会进入catch,并且清楚停止状态值,使之成为false。先interrupt再sleep也会进入catch,此处不做赘述。

  • 异常法
package chapter1.create.threadinterrupt;

public class StopThreadByExceptionTest {
	
	static class MyThread extends Thread{
		
		@Override
		public void run() {
			super.run();
			try {
				for(int i=0;i<500000;i++) {
					if(this.isInterrupted()) {
						System.out.println("已经是停止状态了!我要退出了");
						throw new InterruptedException();
					}
					System.out.println("i="+(i+1));
				}
			} catch (InterruptedException e) {
				System.out.println("进MyThread.java类run方法中的catch了。");
				e.printStackTrace();
			}
		}
	}
	
	public static void main(String[] args) {
		try {
			MyThread myThread = new MyThread();
			myThread.start();
			Thread.sleep(2000);
			myThread.interrupt();
		} catch (Exception e) {
			System.out.println("main catch.");
			e.printStackTrace();
		}
	}

}

 运行结果:
i=420003
i=420004
i=420005
i=420006
i=420007
i=420008
i=420009
i=420010
i=420011
已经是停止状态了!我要退出了
进MyThread.java类run方法中的catch了。
java.lang.InterruptedException
    at chapter1.create.threadinterrupt.StopThreadByExceptionTest$MyThread.run(StopThreadByExceptionTest.java:14)

  • 使用return停止线程:判断this.isInterrupted()为true,return。不过还是建议使用“异常法”,因为在catch块中可以对异常的信息进行相关的处理,而且使用异常流能更好、更方便地控制程序的运行流程。
  • stop()暴力停止。该方法已经被废弃,因为如果强制让线程停止则有可能使一些清理性的工作得不到完成。另外一个情况就是对锁定的对象“解锁”,导致数据得不到同步的处理,出现数据不一致的问题。

 5.线程的优先级

setPriority(int priority):值的范围1-10,设置线程优先级有助于帮“线程规划器”确定在下一次选择哪一个线程来优先执行。

  • 线程的优先级具有继承性,比如A线程启动B线程,则B线程的优先级与A是一样的。
  • 线程的优先级具有一定的规则性,也就是CPU尽量将执行资源让个优先级较高的线程。
  • 线程的优先级具有随机性,也就是优先级较高的线程不一定每一次都先执行。
原文地址:https://www.cnblogs.com/hunter-56213/p/11044756.html