java多线程基础

Posted 知道什么是码怪吗?

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java多线程基础相关的知识,希望对你有一定的参考价值。

目录

实现多线程的两种基础方式

方式一:继承Thread类

方式二:实现Runnable接口

线程常用方法

线程优先级设置

线程的插队和礼让

线程的中断

守护线程 

线程同步

多线程时间比较


实现多线程的两种基础方式

方式一:继承Thread类

java中一个类只能继承一个父类,如果当前类已经继承了其他类了,则不能使用这种方法。

class Way1 extends Thread 

	private boolean bool = true;// 用于控制进程结束

	public void run() // 编写具体的逻辑代码
		while (bool) 
			System.out.println("way1线程执行" + "    线程名为:" + Thread.currentThread().getName());
			try 
				Thread.sleep(100);// 睡眠0.1秒
			 catch (InterruptedException e) 
				e.printStackTrace();
			
		
	

	public boolean isBool() // 可用于查看线程的状态
		return bool;
	

	public void setBool(boolean bool) // 可用于改变线程的状态
		this.bool = bool;
	


public class Text1 

	public static void main(String[] args) throws InterruptedException 
		Way1 way1 = new Way1();
		way1.start();
		Thread.sleep(5000);// 主线程睡眠5秒,这个时候子线程仍然在执行
		way1.setBool(false);// 然后关闭线程
	

方式二:实现Runnable接口

避免了方式一的问题,但是在开启线程的时候代码实现略有不同。

class Way2 implements Runnable 

	private boolean bool = true;// 用于控制进程结束

	@Override
	public void run() // 编写具体的逻辑代码
		while (bool) 
			System.out.println("way2线程执行" + "    线程名为:" + Thread.currentThread().getName());
			try 
				Thread.sleep(100);// 睡眠0.1秒
			 catch (InterruptedException e) 
				e.printStackTrace();
			
		
	

	public boolean isBool() // 可用于查看线程的状态
		return bool;
	

	public void setBool(boolean bool) // 可用于改变线程的状态
		this.bool = bool;
	



public class Text1 

	public static void main(String[] args) throws InterruptedException 
		Way2 way2 = new Way2();
		Thread thread = new Thread(way2);
		thread.start();// new Thread(way2).start();
		Thread.sleep(5000);// 主线程睡眠5秒,这个时候子线程仍然在执行
		way2.setBool(false);// 然后关闭线程
	

线程常用方法

线程优先级设置

// 线程优先级为1~10,不在范围内会抛出异常
// 设置优先级  setPriority();
// 获取优先级  getPriority();

		System.out.println(Thread.MAX_PRIORITY);// 最高优先级:10
		System.out.println(Thread.NORM_PRIORITY);// 一般优先级:5
		System.out.println(Thread.MIN_PRIORITY);// 最低优先级:1

		// 对于方式1实现的多线程
		Way1 way1 = new Way1();
		way1.setPriority(10);// 设置优先级
		System.out.println(way1.getPriority());// 查看优先级

		// 对于方式2实现的多线程
		Way2 way2 = new Way2();
		Thread thread = new Thread(way2);
		thread.setPriority(5);
		System.out.println(way1.getPriority());// 查看优先级

线程的插队和礼让

// 线程的礼让: Thread.yield();   该方法为静态方法,不一定礼让成功。如果资源充足礼让不成功
// 线程的插队: 类名.join();    插队成功后先执行完插入的线程的所有任务,再执行当前线程
// 获取电脑核数:Runtime.getRuntime().availableProcessors();

class Way1 extends Thread 

	private boolean bool = true;// 用于控制进程结束
	private int count = 0;// 记录执行次数

	@Override
	public void run() // 编写具体的逻辑代码
		while (bool) 
			System.out.println((++count) + "   way1线程执行" + "    线程名为:" + Thread.currentThread().getName());
			if (count == 15)
				break;
			try 
				Thread.sleep(100);// 睡眠0.1秒
			 catch (InterruptedException e) 
				e.printStackTrace();
			
		
	

	public boolean isBool() // 可用于查看线程的状态
		return bool;
	

	public void setBool(boolean bool) // 可用于改变线程的状态
		this.bool = bool;
	



public class Text1 

	public static void main(String[] args) throws InterruptedException 

		Way1 way1 = new Way1();
		way1.start();

		for (int i = 1; i <= 10; i++) 
			Thread.sleep(100);
			System.out.println(i + "   主线程执行" + "   线程名为:" + Thread.currentThread().getName());
			if (i == 5)
				way1.join();//**本来同时执行,让way1插队先执行**
		
	

运行结果:

线程的中断

//线程中断:  类名.interrupt();    不是中止是中断


class Way1 extends Thread 

	private boolean bool = true;// 用于控制进程结束
	private int count = 0;

	@Override
	public void run() // 编写具体的逻辑代码
		while (bool) 
			for (int i = 1; i <= 5; i++) // 输出5次停20秒
				System.out.println((i) + "   way1线程执行" + "    线程名为:" + Thread.currentThread().getName());
			
			try 
				Thread.sleep(200000);//停200秒
			 catch (InterruptedException e) 
				System.out.println("捕获中断");
			
		
	

	public boolean isBool() // 可用于查看线程的状态
		return bool;
	

	public void setBool(boolean bool) // 可用于改变线程的状态
		this.bool = bool;
	



public class Text1 

	public static void main(String[] args) throws InterruptedException 

		Way1 way1 = new Way1();
		way1.start();

		for (int i = 1; i <= 10; i++) 
			Thread.sleep(5000);//5秒过后
			way1.interrupt();//**提前结束休眠再次启动**
		
	

运行结果: 

守护线程 

/*
 * 设置守护线程: 类名.setDaemon();   当主线程下有子线程时 如果子线程可以无限的执行,那么当主线程执行结束后,子线程并不会结束。
 * 如果我们想子线程随着主线程一同结束,就要设置为守护线程
 */
class DaemonThread extends Thread 

	private boolean bool = true;// 用于控制进程结束
	private int count = 0;

	@Override
	public void run() // 编写具体的逻辑代码
		while (bool) 
			System.out.println((++count) + "   子线程执行" + "    线程名为:" + Thread.currentThread().getName());
			try 
				Thread.sleep(1000);
			 catch (InterruptedException e) 
				e.printStackTrace();
			
		
	

	public boolean isBool() // 可用于查看线程的状态
		return bool;
	

	public void setBool(boolean bool) // 可用于改变线程的状态
		this.bool = bool;
	



public class Text1 

	public static void main(String[] args) throws InterruptedException 

		DaemonThread dt = new DaemonThread();
		dt.setDaemon(true);//**设置为守护线程,当主线程结束时子线程一同结束**
		dt.start();

		for (int i = 1; i <= 5; i++) 
			System.out.println((i) + "   主线程执行" + "    线程名为:" + Thread.currentThread().getName());
			Thread.sleep(1000);// 5秒过后
		
	

运行结果:

线程同步

java线程同步 synchronized详解
 

多线程时间比较

通过使用欧拉筛求素数、朴素方法求素数、多线程朴素方法求素数来进行时间比较,多线程消耗的时间是一个大概的值,不是准确的。因为在求素数的过程中,程序执行的太快了,多个线程有可能拿了同一个数做运算,这就导致多线程的运算量大于的朴素方法。

class GetPrime extends Thread 

	public static int count = 2;
	public static int num = 0;// 记录素数个数
	public int n;// 求素数的范围
	long startTime;
	long endTime;
	public static boolean[] bool = new boolean[10000000];//减少重复计算

	GetPrime(int n) 
		this.n = n;
	

	@Override
	public void run() // 编写具体的逻辑代码
		while (count <= n) //多线程求素数的时候有可能count还没有加1,另一个线程拿了相同的数做比较,这样写是为了减少重复的计算,但仍然不彻底
			if (bool[count] == false) //这个数没有拿过,拿过来标记为true
				bool[count] = true;
				int a = count;
				count++;
				if (Prime(a) == true)
					num++;
			 else
				count++;
		
		endTime = System.currentTimeMillis(); // 获取开始时间
	

	public static boolean Prime(int number) // 朴素方法求素数

		for (int i = 2; i <= Math.sqrt(number); i++) 
			if (number % i == 0)
				return false;
		
		return true;
	


public class Text1 

	public static void GetPrime(int n) // 欧拉筛求素数,素数都被保留在prime数组当中
		int[] prime = new int[n + 10];
		boolean[] bool = new boolean[n + 10];
		int count = 0;
		for (int i = 2; i <= n; i++) 
			if (bool[i] == false) 
				prime[count++] = i;
				bool[i] = true;
			
			for (int j = 0; j < count; j++) 
				if (i * prime[j] > n)
					break;
				bool[i * prime[j]] = true;
				if (i % prime[j] == 0)
					break;
			
		
		System.out.println(count);// 输出个数
	

	public static boolean Prime(int number) // 朴素方法求素数

		for (int i = 2; i <= Math.sqrt(number); i++) 
			if (number % i == 0)
				return false;
		
		return true;
	

	public static void main(String[] args) throws InterruptedException 
		int count = 0;
		int n = 1000000;
		long startTime = System.currentTimeMillis(); // 获取开始时间
		GetPrime(n);
		long endTime = System.currentTimeMillis(); // 获取结束时间
		System.out.println("欧拉筛程序运行时间:" + (endTime - startTime) + "ms"); // 输出程序运行时间

		// 6977
		startTime = System.currentTimeMillis(); // 获取开始时间
		for (int i = 2; i <= n; i++) 
			if (Prime(i) == true)
				count++;
		
		System.out.println(count);// 输出个数
		endTime = System.currentTimeMillis(); // 获取结束时间
		System.out.println("朴素for循环程序运行时间:" + (endTime - startTime) + "ms"); // 输出程序运行时间

		startTime = System.currentTimeMillis(); // 获取开始时间
		GetPrime P1 = new GetPrime(n);
		GetPrime P2 = new GetPrime(n);
		GetPrime P3 = new GetPrime(n);
		GetPrime P4 = new GetPrime(n);
		P1.start();//开4个线程
		P2.start();
		P3.start();
		P4.start();
		Thread.sleep(1000);
		System.out.println(GetPrime.num);// 输出个数
		endTime = System.currentTimeMillis(); // 获取结束时间
		System.out.println("朴素多线程for循环程序运行时间:" + (P1.endTime - startTime) + "ms"); // 输出程序运行时间

	

运行结果:

可以看到,多线程在做了许多重复的计算过后,消耗的时间仍然比朴素for循环快。

也可以看到,多线程没有欧拉筛快,说明算法对效率的提高是多么的大!!!

以上是关于java多线程基础的主要内容,如果未能解决你的问题,请参考以下文章

java基础入门-多线程同步浅析-以银行转账为样例

java多线程基础

Java基础之多线程

Java多线程基础

多线程编程学习一(Java多线程的基础)

Java 多线程基础多线程的实现方式