Java教程

Java中的多线程@造型专家_day_20_20210416

本文主要是介绍Java中的多线程@造型专家_day_20_20210416,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

java中的多线程

  提到多线程,就得提提什么是线程,什么是进程,什么是程序了
  如下图所示:
图示1
下面是cpu:
  a)单核CPU,其实是一种假的多线程,因为在一个时间单元内,也只能执行一个线程的任务。例如:虽然有多车道,但是收费站只有一个工作人员在收费,只有收了费才能通过,那么CPU就好比收费人员。如果有某个人不想交钱,那么收费人员可以把他“挂起”(晾着他,等他想通了,准备好了钱,再去收费)。但是因为CPU时间单元特别短,因此感觉不出来。
  b)如果是多核的话,才能更好的发挥多线程的效率。(现在的服务器都是多核的)c)一个Java应用程序java.exe,其实至少有三个线程:main0主线程,gc0垃圾回收线程,异常处理线程。当然如果发生异常,会影响主线程。
  
下面是并发和并行:
  并行:多个CPU同时执行多个任务。比如:多个人同时做不同的事。
  并发:一个CPU(采用时间片)同时执行多个任务。比如:秒杀、多个人做同一件事
  
  以单核CPU为例,只使用单个线程先后完成多个任务(调用多个方法),肯定比用多个线程来完成用的时间更短,为何仍需多线程呢?
  1.提高应用程序的响应。对图形化界面更有意义,可增强用户体验。
  2.提高计算机系统CPU的利用率
  3.改善程序结构。将既长又复杂的进程分为多个线程,独立运行,利于理解和修改
  
  多线程的应用场景:
~程序需要同时执行两个或多个任务。
~程序需要实现一些需要等待的任务时,如用户输入、文件读写操作、网络操作、搜索等。
~需要一些后台运行的程序时
  
线程创建有两种方式
1.创建线程的第一种方式
  创建类继承Thread类
  覆写run()方法,run方法就等于是新线程中的main方法,是程序执行的起点和终点
  启动线程手动调用当前线程对象的start)方法不是run方法
如下图:
图示2
图示3
下面是源码:
package day_20_Test;

/*

  • 编写多线程环境下较安全的单例模式
    */

public class Homework_02 {

public static void main(String[] args) {
	//main方法中创建三个线程
	Thread t1 = new CreateThread();
	Thread t2 = new CreateThread();
	Thread t3 = new CreateThread();
	
	//启动
	t1.start();
	t2.start();
	t3.start();
}

}

//单例类
class SingLeton{
//单例模式构造方法需要私有化
private SingLeton(){
super();
}

//饿汉模式,什么时候创建对象什么时候赋值
private static SingLeton obj = null;

//用户想要创建对象,需要用我们提供的方法,因为需要多线程安全,所以这里加上synchronized
public synchronized static SingLeton createObj(){
	if(obj == null){
		obj = new SingLeton();
		obj.printObj();
		return obj;
	}
	else{
		System.out.println("拿到已有对象");
		return obj;
	}

}

//写一个成员方法打印输出,测试是否创建对象
public void printObj(){
	System.out.println(this);
}

@Override
public String toString() {
	return "这是单例模型的一个对象";
}

}

//继承thread类的创建线程类
class CreateThread extends Thread{

@Override
public void run() {
	//在这里面调用方法创建对象
	SingLeton.createObj();
}

}

2.创建线程的第二种方式
  实现Runnable接口,覆写run方法
  启动线程调用Thread的start方法
图示4
图示5
下面是源码:

package day_20_Test;

import java.util.Random;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/*

  • 声明一个共享数组,起两个线程,两个线程分别隔一段时间(可以写一个随机数)
  • 给数组中添加数据,每一个线程为数组添加3个数据即可。

*/

public class Homework_03 {

public static void main(String[] args) throws InterruptedException {
	//起两个线程
	Thread t1 = new Thread(new CreateThread2());
	Thread t2 = new Thread(new CreateThread2());
	t1.setName("线程1");
	t2.setName("线程2");
	t1.start();
	t2.sleep(500);
	t2.start();
}

}

//下面是实现接口的创建线程类
class CreateThread2 implements Runnable{
//声明一个整型共享数组sharearrays
public static int sharearrays[] = new int[6];

//定义一个成员变量,来保存一个线程一共运行几次
private int count;

public void run() {
	for (int i = 0 ; i<6 ; i++ ){
		//创建锁对象
		Lock lock = new ReentrantLock();
		//加锁,锁内数据只能一个线程执行
		lock.lock();
		try {
			//添加数据
			addNumber(i);
			System.out.println(Thread.currentThread().getName()+"添加"+(count+1)+"次");
		}finally{
			//解锁
			lock.unlock();
		}
		//为了防止一个线程直接完成,这里睡眠随机数长的时间
		try {
			Thread.sleep(1000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		//计数值+1
		count++;
		//当计数值达到3跳出
		if(count >= 3){
			return;
		}
	}
	//count等于0,1,2执行,否则跳出
	
	//因为每个线程为数组提供三个数据,所以在线程中肯定需要判断是否够三个
}

//写一个生成随机数的方法,返回值为int型
private static int createRandom(){
	//写一个随机数,先写个从1到10的吧
	Random random = new Random();
	return random.nextInt(10)+1;
}

//定义一个往数组中添加数据的方法
private void addNumber(int i){
	sharearrays[i] = createRandom();
	System.out.println("添加的数据值为"+sharearrays[i]);
}

}

  以上就是今天学习比较深刻的理解了,希望能对查询到这篇文章的朋友有帮助,以及自己日后可以继续查看。

这篇关于Java中的多线程@造型专家_day_20_20210416的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!