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循环快。

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

  • 11
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

算不出来没办法

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值