Java基础之多线程汇总一

本文详细介绍了Java中的多线程基础知识,包括进程与线程的区别、线程的创建与执行、线程间的资源竞争、线程状态、线程同步与锁机制,以及线程生命周期。通过实例展示了如何使用Thread类和Runnable接口创建线程,同时探讨了线程优先级、自定义名称、休眠、礼让、合并、中断和守护线程等特性。此外,还讨论了线程局部变量以及线程安全问题。
摘要由CSDN通过智能技术生成

多线程基础

一、什么是进程

进程是系统进行资源分配和调用的独立单元,每一个进程都有它的独立内存空间和系统资源。

二、单进程操作系统和多进程操作系统的区别

单进程操作系统:dos(一瞬间只能执行一个任务)

多进程单用户操作系统:Windows(一瞬间只能执行多个任务)

多进程多用户操作系统:Linux(一瞬间只能执行多个任务)

三、现在的多核CPU是否可以让系统在同一个时刻可以执行多个任务吗?

理论上是可以的

四、什么是线程,理解线程和进程的关系

什么是线程?

线程是进程里面的一条执行路径,每个线程同享进程里面的内存空间和系统资源

一个进程 可以有 多个线程:各个线程都有不同的分工

理解线程和进程的关系

进程 与 进程 之间的关系:进程之间的内存空间和系统资源是独立的

同一个进程里的多条线程 :线程之间的内存空间和系统资源是共享的

进程里:可以有一条或一条以上的线程

进程里只有一条线程的情况下,这条线程就叫做主线程

进程里有多条线程的情况下,只有一条线程叫做主线程

Ps:线程是在进程里的,他们是包含关系

五、我们应用的软件有哪些是多线程的应用?

都是

六、Java中,如何来编写多线程的应用程序?有哪些方法?

1.线程类

创建MyThread类,继承Thread,重写run方法

public class Test01 {
	
	public static void main(String[] args) {
		
		//创建线程的对象
		MyThread t = new MyThread();
		//启动线程
		t.start();
	}
}
//线程类
class MyThread extends Thread{
	
	//当前线程抢到cpu资源后,就会执行run方法
	@Override
	public void run() {
		System.out.println("当前线程抢到资源了");
	}
}

2.任务类

创建Task类,实现Runnable接口中的run方法

public class Test01 {
	
	public static void main(String[] args) {
		
		Thread t = new Thread(new Task());
		t.start();
	}
}
//任务类
class Task implements Runnable{

	//当前线程抢到cpu资源后,就会执行run方法
	@Override
	public void run() {
		System.out.println("抢到资源了");
	}
}

3.带返回值的任务类

4.线程池

七、感受多线程之间争抢资源的场景

需求:编写一个多线程的应用程序,主线程打印1-100之间的数字,子线程打印200-300之间的数字,观察其输出的结果,体会多线程互相争抢资源的场景

八、小结

进程 与 进程 的关系:独享内存空间和系统资源

线程 与 进程 的关系:有一个进程中至少包含一个线程

线程 与 线程 的关系:在同一个进程里,多个线程共享内存空间和系统资源

一个进程中包含多个线程,只有一个主线程

经典面试题:请问当我们编写一个单纯的main方法时,此时该程序是否为单线程的?为什么?

垃圾回收器是一个后台线程

九、线程的优先级别

需求:在主线程中创3个子线程,并且设置不同优先级,观察其优先级对线程执行结果的”影响”。

a.setPriority(Thread.MAX_PRIORITY);//10
b.setPriority(Thread.NORM_PRIORITY);//5
c.setPriority(Thread.MIN_PRIORITY);//1

优先级只是有影响,不能决定最终结果

十、给线程自定义名称

  1. 自己写getThreadName/setThreadName
  2. 调用父类的一个参数的构造方法和getName
  3. Thread.currentThread().getName()

十一、让线程休眠

需求:编写一个抽取学员回答问题的程序,要求倒数三秒后输出被抽中的学员姓名

Thread.sleep(1000);

此方法为静态方法,写在哪个线程中,哪个线程就休眠

十二、线程的礼让

需求:创建两个线程A,B,分别各打印1-100的数字,其中B一个线程,每打印一次,就礼让一次,观察实验结果

Thread.yield();

此方法为静态方法,此方法写在哪个线程中,哪个线程就礼让

所谓的礼让是指当前线程退出CPU资源,并转到就绪状态,接着再抢

十三、线程的合并

需求:主线程和子线程各打印200次,从1开始每次增加1,当主线程打印到10之后,让子线程先打印完再打印主线程

t.join(); 合并方法

十四、线程的中断

@Override
public void run() {		
    //isInterrupted() - 获取当前线程状态(true-中断 false-存活)
    while(!Thread.currentThread().isInterrupted()){		
        System.out.println("111");
        System.out.println("222");
        System.out.println("333");
        System.out.println("444");
    }
}
MyThread t = new MyThread();
t.start();
Thread.sleep(3000);
t.interrupt();//改变线程状态

十五、守护线程

守护线程 默默守护着前台线程,当所有的前台线程都消亡后,守护线程会自动消亡

注意:垃圾回收器就是守护线程

t.setDaemon(true);

@Override
public void run() {
    while(true){
        System.out.println("守护线程默默守护着前台线程...");
        try {
            //父类run方法没有抛异常,子类重写后也不能抛异常
            Thread.sleep(1000);
        } catch (InterruptedException e) {
        }
    }
}
GuardThread guardThread = new GuardThread();
guardThread.setDaemon(true);//将此线程设置为后台线程
guardThread.start();
for (int i = 1; i <=5; i++) {
    System.out.println("前台线程:" + i);
    Thread.sleep(1000);
}

十六、线程局部变量(实现线程范围内的共享变量)

  1. 共享单个数据,注意线程安全

ConcurrentHashMap<Thread, T>

map.put(Thread.currentThread(), T);

  1. 共享多个数据

public static ConcurrentHashMap<Thread, Data> map = new ConcurrentHashMap<>();

Data data = new Data(20,“bbb”);
//存数据
map.put(Thread.currentThread(), data);

  1. 共享多个数据
public class Test01 {
	public static ThreadLocal<Data> local = new ThreadLocal<>();
	public static void main(String[] args) {
	//共享多个变量的情况 - ThreadLocal
		new Thread(new Runnable() {
			@Override
			public void run() {
				Data data = Data.getInstance(10,"aaa");
				//存数据
				local.set(data);
                
				A a = new A();
				B b = new B();
				a.println();//10
				b.println();//10
			}
		},"线程1").start();
		
		new Thread(new Runnable() {
			@Override
			public void run() {
				Data data = Data.getInstance(20,"bbb");
				//存数据
				local.set(data);
				A a = new A();
				B b = new B();
				a.println();//20
				b.println();//20
			}
		},"线程2").start();
	}
}
//数据包类
public class Data {
	
	private int i;
	private String str;
	//有参无参构造。。。。。
	//获取数据包的对象
	public static Data getInstance(int i,String str){
		Data data = Test01.local.get();
		if(data == null){
			data = new Data(i, str);
			Test01.local.set(data);
		}else{
			data.setI(i);
			data.setStr(str);
		}
		return data;
	}
	//get set toString方法。。。。。
}

十七、线程的生命周期

1、新建状态

i. 在程序中用构造方法创建了一个线程对象后,新的线程对象便处于新建状态,此时,它已经有了相应的内存空间和其它资源,但还处于不可运行状态。新建一个线程对象可采用线程构造方法来实现。

ii. 例如:Thread thread=new Thread();

2、 就绪状态

i. 新建线程对象后,调用该线程的start()方法就可以启动线程。当线程启动时,线程进入就绪状态。此时,线程将进入线程队列排队,等待CPU调用,这表明它已经具备了运行条件。

3、运行状态

i. 当就绪状态的线程被调用并获得处理器资源时,线程就进入了运行状态。此时,自动调用该线程对象的run()方法。run()方法定义了该线程的操作和功能。

4、 阻塞状态

i. 一个正在执行的线程在某些特殊情况下,如被人为挂起,将让出CPU并暂时中止自己的执行,进入阻塞状态。在可执行状态下,如果调用sleep(2000)、wait()等方法,线程都将进入阻塞状态。阻塞时,线程不能进入排队队列,只有当引起阻塞的原因被消除后,线程才可以转入就绪状态。

5、死亡状态

i. 线程调用stop()方法时或run()方法执行结束后,线程即处于死亡状态。处于死亡状态的线程不具有继续运行的能力。

案例

1.计算任务,一个包含了2万个整数的数组,分拆了多个线程来进行并行计算,最后汇总出计算的结果。

2.铁道部发布了一个售票任务,要求销售1000张票,要求有3个窗口来进行销售,请编写多线程程序来模拟这个效果

i. 窗口001正在销售第1000张票

ii. 窗口001正在销售第999张票

iii. 窗口002正在销售第998张票

iv. 。。。

v. 窗口002正在销售第1张票

涉及到线程安全,要加锁

线程安全(锁)

继承Thread类

  1. synchronized (){}注意锁对象要相同才能互斥住线程
java伪代码(同步锁的三种方式):
	同步代码块:
    synchronized(锁对象){//自动上锁
    ...要互斥住的代码... 	
    }//自动解锁 
    同步方法:
    //锁对象:this
    public synchronized void method01(){//自动上锁
    ...要互斥住的代码... 	
    }//自动解锁
	//锁对象:类的字节码文件对象 	
	public static synchronized void method02(){//自动上锁
    ...要互斥住的代码... 	
    }//自动解锁
  1. Lock
Lock lock = new ReentrantLock(); 
lock.lock();//手动上锁 ...要互斥住的代码... 
lock.unlock();//手动解锁 

实现Runnable接口

Task task = new Task();//只new了一个对象,Task很多东西不需要加static
Thread t1 = new Thread(task, "窗口001");
Thread t2 = new Thread(task, "窗口002");

实现线程安全的方法还是和上面一样。

注:本篇文章是结合hhy老师所给资料再汇总整理所得,还有多线程模型和线程池在后面的文章发。
帅哥声明:才开始写博文不久,如果有什么地方写的不对的还请指出,谢谢!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

cat_lkh

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

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

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

打赏作者

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

抵扣说明:

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

余额充值