Java多线程基础知识总结(一)

终于有机会总结一下多线程了,java的多线程一直是一个重要的问题(在面试中),所以了解java的多线程的知识对找一个好工作至关重要。
今天正好在准备面试,就简单的总结一下java的多线程的知识。

多线程的实现方法

多线程的实现方法有两种,一种方法是继承Thread,并实现其中的run方法;另一种是实现runnable接口:

//1、继承thread
public class New_thread extends Thread{
	public void run() {
		System.out.println(Thread.currentThread().getName());
	}
}
public class Test_thread{
	public static void main(String[] args) {
		New_thread run=new New_thread();
		run.start();
		System.out.println("测试完成");
	}
}
//2、实现runnable接口
public class New_runnable implements Runnable{
	public void run(){
		System.out.println("running!");
	}
}
public class Test_thread{
	public static void main(String[] args) {
		New_runnable run=new New_runnable();
		Thread test=new Thread(run);
		test.start();
		System.out.println("测试完成");
	}
}

一旦涉及多线程就有可能造成数据的不一致性,会有共享数据的竞争条件。
如下所示代码:

public class New_thread extends Thread{
	private int count=5;
	public void run() {
		count--;
		System.out.println(count+" "+Thread.currentThread().getName());
	}
}

public class Test_thread{
	public static void main(String[] args) {
		New_thread test=new New_thread();
		Thread t1=new Thread(test);
		Thread t2=new Thread(test);
		Thread t3=new Thread(test);
		Thread t4=new Thread(test);
		Thread t5=new Thread(test);
		t1.start();t2.start();t3.start();t4.start();t5.start();
	}
}

上述代码运行结果为:

java 多线程的三种写法 java多线程总结_java 多线程的三种写法

synchronized关键字

这个关键字的作用是:让标志以后的代码进行顺序执行,而不是并行执行。这样可以有效的解决刚刚的数据的不一致性的问题。

public class New_thread extends Thread{
	private int count=5;
	synchronized public void run() {
		count--;
		System.out.println(count+" "+Thread.currentThread().getName());
	}
}

运行以后结果为:

java 多线程的三种写法 java多线程总结_Test_02

currentThread方法

返回当前运行的线程

public class New_thread extends Thread{
	public New_thread() {
		System.out.println(Thread.currentThread().getName());
		System.out.println(this.getName());
	}
	synchronized public void run() {
		System.out.println(Thread.currentThread().getName());
		System.out.println(this.getName());
	}
}
public class Test_thread{
	public static void main(String[] args) {
		New_thread test=new New_thread();
		Thread a=new Thread(test);
		a.setName("a");
		a.start();;
	}
}

java 多线程的三种写法 java多线程总结_java_03

isAlive()方法

判断当前线程是否处于活跃状态。当前线程是currentThread返回的线程的名称

public class New_thread extends Thread{
	public New_thread() {
		System.out.println(Thread.currentThread().getName());
		System.out.println(Thread.currentThread().isAlive());
		System.out.println(this.getName());
		System.out.println(this.isAlive());
	}
	public void run() {
		System.out.println(Thread.currentThread().getName());
		System.out.println(Thread.currentThread().isAlive());
		System.out.println(this.getName());
		System.out.println(this.isAlive());
	}
}
public class Test_thread{
	public static void main(String[] args) {
		New_thread test=new New_thread();
		Thread t=new Thread(test);
		System.out.println("1   "+t.isAlive());
		t.setName("T");
		t.start();
		System.out.println("2   "+t.isAlive());
	}
}

java 多线程的三种写法 java多线程总结_System_04


这次的运行结果表示,当前运行的线程并不一定是我们定义的线程,也有可能是当前调用管理我们的线程的线程,所以程序的输出结果是有差异的。

thread.sleep()方法

让“正在执行的线程”进入休眠,休眠指定毫秒数,“正在执行的线程”是指this.currentThread返回的线程

public class New_thread extends Thread{
	public void run() {
		try {
			System.out.println(this.currentThread().getName()+" "+System.currentTimeMillis());
			Thread.sleep(1000);
			System.out.println(this.currentThread().getName()+" "+System.currentTimeMillis());
		}catch(InterruptedException e) {
			e.printStackTrace();
		}
	}
}
public class Test_thread{
	public static void main(String[] args) {
		try {
		New_thread test=new New_thread();
		System.out.println(System.currentTimeMillis());
		test.start();
		Thread.sleep(2000);
		System.out.println(System.currentTimeMillis());
		}catch(InterruptedException e) {
			e.printStackTrace();
		}
	}
}

java 多线程的三种写法 java多线程总结_多线程_05

getId()方法

作用是取得线程的唯一的标识。当当前执行代码的线程名称是main的时候,线程id值设置为1。其余的标识大家可以自行尝试。

停止线程

停止线程是一个有意思的事情,因为线程没有像break的方法来进行停止的方法。绝大多数使用interrupt的方法来停止一个线程。但是并不是终止一个正在运行的进程,还需要加入一个判断才可以完成线程的终止。
java有三种终止线程的方法:
1、使用退出标志;
2、使用stop方法强行终止一个线程;
3、使用interrupt方法中断线程。

interrupt方法

interrupt方法没有办法直接的停止线程,只能简单的打下标记

public class New_thread extends Thread{
	public void run() {
		for(int i=0;i<50000l;i++) {
			System.out.println(i+1);
		}
	}
}
public class Test_thread{
	public static void main(String[] args) {
		try {
			New_thread test=new New_thread();
			test.start();
			Thread.sleep(2000);
			Thread.interrupted();
		}catch(InterruptedException e) {
			System.out.println("main catch");
			e.printStackTrace();
		}
	}
}

java 多线程的三种写法 java多线程总结_java 多线程的三种写法_06


想要真正的停止一个线程需要加一个判断条件,在判断条件中加入真正停止的方法。

判断是否停止的方法

public class Test_thread{
	public static void main(String[] args) {
		Thread.currentThread().interrupt();
		System.out.println(Thread.currentThread().interrupted());
		System.out.println(Thread.currentThread().interrupted());
	}
}

结果:

java 多线程的三种写法 java多线程总结_java 多线程的三种写法_07

public class Test_thread{
	public static void main(String[] args) {
		Thread.currentThread().interrupt();
		System.out.println(Thread.currentThread().isInterrupted());
		System.out.println(Thread.currentThread().isInterrupted());
	}
}

结果:

java 多线程的三种写法 java多线程总结_java 多线程的三种写法_08


this.interrupted():测试当前线程是否已经中断,执行以后将状态标志清除为false的功能

this.isInterrupted():测试线程是否已经中断,但是不清除状态标志

下面介绍能够终止线程的方法:

第一种,异常终止法:

将终止以后的线程打入“冷宫”——错误捕捉部分代码,就永远别想出来啦。

public class New_thread extends Thread{
	public void run() {
		try {
			for(int i=0;i<50;i++) {
				System.out.println(i+1);
				if(this.interrupted()) {
					throw new InterruptedException();
				}
			}
		}catch(InterruptedException e) {
			System.out.println("打入冷宫!永远不得外出");
			e.printStackTrace();
		}
	}
}
public class Test_thread{
	public static void main(String[] args) {
		try {
			New_thread test=new New_thread();
			test.start();
			Thread.sleep(1);
			test.interrupt();
		}catch(InterruptedException e) {
			e.printStackTrace();
		}
	}
}

运行结果:

java 多线程的三种写法 java多线程总结_System_09


第二种、睡眠终止法:

在睡梦中被终止,可怜的线程。

public class New_thread extends Thread{
	public void run() {
		try {
			System.out.println("开始运行");
			Thread.sleep(20000);
			System.out.println("运行结束");
		}catch(InterruptedException e) {
			System.out.println("在睡梦中被杀死,可怜的线程!");
			e.printStackTrace();
		}
	}
}
public class Test_thread{
	public static void main(String[] args) {
		try {
			New_thread test=new New_thread();
			test.start();
			Thread.sleep(100);
			test.interrupt();
		}catch(InterruptedException e) {
			e.printStackTrace();
		}
	}
}

结果:

java 多线程的三种写法 java多线程总结_Test_10


第三种、暴力终止法

说一句实话,我就是很喜欢这种方法,暴力简单直接。

public class New_thread extends Thread{
	public void run() {
		try {
			for(int i=0;i<50;i++) {
				System.out.println(i+1);
				this.sleep(1);
			}
		}catch(InterruptedException e) {
			e.printStackTrace();
		}
	}
}
public class Test_thread{
	@SuppressWarnings("deprecation")
	public static void main(String[] args) {
		try {
			New_thread test=new New_thread();
			test.start();
			Thread.sleep(10);
			test.stop();
		}catch(InterruptedException e) {
			e.printStackTrace();
		}
	}
}

结果:

java 多线程的三种写法 java多线程总结_Test_11


stop方法可以抛出ThreadDeath的异常,使用起来如下所示:

public class New_thread extends Thread{
	public void run() {
		try {
			this.stop();
		}catch(ThreadDeath e) {
			System.out.println("一个出生就为了自杀的线程!");
			e.printStackTrace();
		}
	}
}
public class Test_thread{
	public static void main(String[] args) {
		try {
			New_thread test=new New_thread();
			test.start();
			Thread.sleep(1000);
		}catch(InterruptedException e) {
			e.printStackTrace();
		}
	}
}

虽然我很喜欢stop但是总是有很多人说stop方法不好,会造成很多的数据的不一致性,好吧,这个确实有问题,但是什么代码没有风险呢?个人觉得只要小心,明白原理,任何代码都可以发挥它应有的作用的。
举个小栗子吧!

public class LoginClass {
	private String usr="1";
	private String psw="111";
	public void setString(String s1,String s2){
		try {
		this.usr=s1;
		if(this.usr.equals("a")) {
			Thread.sleep(10000);
		}
		this.psw=s2;
		}catch(InterruptedException e) {
			e.printStackTrace();
		}
	}
	public String printString() {
		return usr+" "+psw;
	}
}
public class New_thread extends Thread{
	private LoginClass object;
	public New_thread(LoginClass object) {
		this.object=object;
	}
	public void run() {
		object.printString("b", "bb");
	}
}
public class Test_thread{
	public static void main(String[] args) {
		try {
			LoginClass object=new LoginClass();
			New_thread test=new New_thread(object);
			test.start();
			Thread.sleep(10);
			test.stop();
			System.out.println(object.getName()+" "+object.getPass());
		}catch(InterruptedException e) {
			e.printStackTrace();
		}
	}
}

java 多线程的三种写法 java多线程总结_System_12


使用return终止线程

public class New_thread extends Thread{
	public void run() {
		for(int i=0;i<50;i++) {
			System.out.println(i+1);
			if(this.interrupted()) {
				return;
			}
		}
	}
}
public class Test_thread{
	public static void main(String[] args) {
		try {
			New_thread test=new New_thread();
			test.start();
			test.interrupt();
			Thread.sleep(10);
		}catch(InterruptedException e) {
			e.printStackTrace();
		}
	}
}

当然大部分人最建议使用抛出异常的方式,我也是这样(虽然我很喜欢暴力终止的方法),毕竟有了异常就可以将异常向上抛去,将线程终止的事件传播开来。

java 多线程的三种写法 java多线程总结_Test_13


今天先写到这里,线程的内容太多太多,今天大概只写了一半的内容,另外一半另发一篇文章,方便大家查阅。