Java多线程

一,单 CPU 如何同时运行多个程序

假设我们同时开了多个程序:Word,IE,QQ,Winamp,对于操作系统来说,这意味着
有四个进程要同时运行。为了解决这个问题,计算机规定了:让这四个进程轮流使用 CPU,
每个进程用一小会儿。这个“一小会儿”,往往是若干个毫秒,这段时间被称为一个“CPU
时间片”。这样,每一秒钟可能有成百上千个 CPU 时间片。从微观上来看,每一个特定的时刻,
CPU 上只有一个程序在运行,宏观上并行,微观上串行。
在这里插入图片描述

二,CPU 核心数

核心数是主板上实际插入的 cpu 硬件个数,一般指物理核心数,也就是硬件上存在有几个核心,也被称为内核。双核就是包括 2 个独立的 CPU 核心单元组,一核 CPU 相当于 1 个人处理数据,双核 CPU 相当于 2 个人处理同一个数据,因此处理核心数越多,CPU 的工作效率也就越高。

三,CPU 线程数

线程是程序运行流的最小单元,一个程序是由一个或多个线程组成。源于多任务处理的需要,线程数越多,越有利于同时运行多个程序,因为线程数等同于在某个瞬间 CPU 能同时并行处理的任务数。
四,CPU 核心数和线程数有什么作用
多核心和多线程的作用主要是为了满足各类程序多任务需求,核心数和线程数量越多,那么越有利同时运行多个程序,CPU 能够并行处理多个任务数量,说白点就是核心数和线程数量越多,越适合多开软件或者游戏,打开的任务越多,除了多开程序,还有渲染需求,核数和线程数越多,越有利,
一个核心一个线程,自超线程技术问世后,一个核心可以同时 2 个线程了。使 CPU 性能上升百分之 40

五,线程运行

CPU、代码、数据,是线程运行时所需要的三大条件。在这三大条件中,CPU 是操作系统分配的,Java 程序员无法控制;数据这部分,需要把握住“堆空间共享,栈空间独立”的概念;

六, Thread 类与 Runnable 接口
class MyThread1 extends Thread   重写run方法,调用start启动线程
class MyRunnable2 implements Runnable   重写run方法,调用start启动线程
七,线程状态

在这里插入图片描述
初始状态:当我们创建了一个线程对象,而没有调用这个线程对象的 start()方法时,此
时线程处于初始状态。
可运行状态:处于可运行状态下的线程,具有这样的特点:线程已经为运行做好了完全
的准备,只等着获得 CPU 来运行。也就是说,线程是万事俱备,只欠 CPU。
运行状态:处于这种状态的线程获得了 CPU 时间片,正在执行代码。由于系统中只有
一个 CPU,因此,同时只能有一个线程处于运行状态。当 CPU 时间片到期而线程没有执行完毕时,
操作系统会把处于运行状态的线程转换成可运行状态,然后再重新从可运行状态中选取一个
线程,为其分配 CPU 时间片。这就是运行状态和可运行状态之间的转换。
终止状态:当一个线程执行完了 run()方法中的代码,该线程就会进入终止状态。

八,sleep()与阻塞:

线程运行不仅需要 CPU 进行运算,还需要一些别的条件,例
如等待用户输入、等待网络传输完成,等等。如果线程正在等待其他的条件完成,在这种情
况下,即使线程获得了 CPU 时间片,也无法真正运行。因此,在这种情况下,为了能够不
让这些线程白白占用 CPU 的时间,会让这些线程会进入阻塞状态。最典型的例子就是等待
I/O,也就是说,如果线程需要与 JVM 外部进行数据交互的话(例如等待用户输入、读写文
件、网络传输等),这个时候,当数据传输没有完成时,线程即使获得 CPU 也无法运行,因
此就会进入阻塞状态。
在这里插入图片描述
如上图所示,除了等待 I/O 会进入阻塞状态之外,还可以调用 Thread 类的 sleep 方法进
入阻塞状态。
public static void sleep(long millis) throws InterruptedException

join():除了使用 sleep()和等待 IO 之外,还有一个方法会导致线程阻塞,这就是线程的 join()
方法
public final void join() throws InterruptedException //有可能出现无线等待情况
public final void join(long millis) throws InterruptedException //阻塞一定事件继续执行

九,线程同步

临界资源与数据不一致
多个线程并发访问同一个对象,如果破坏了不可分割的操作,则有可能产生数据不一致的情况。
这其中,有两个专有名词:被多个线程并发访问的对象,也被称之为“临界资源”;而
不可分割的操作,也被称之为“原子操作”。产生的数据不一致的问题,也被称之为“同步
问题。要产生同步问题,多线程访问“临界资源”,破坏了“原子操作”,这两个条件缺一不
可。

十,synchronized 与同步代码块

Java 中采取了类似的机制,也采用锁来保护临界资源,防止数据不一致的情况产生。
在 Java 中,每个对象都拥有一个“互斥锁标记”,这就好比是我们说的挂锁。这个锁标
记,可以用来分给不同的线程。之所以说这个锁标记是“互斥的”,因为这个锁标记同时只
能分配给一个线程。光有锁标记还不行,还要利用 synchronized 关键字进行加锁的操作。synchronized 关键字有两种用法,我们首先介绍第一种:synchronized + 代码块。

这种用法的语法如下:
synchronized(obj){
代码块…
}

synchronized 关键字后面跟一个圆括号,括号中的是某一个引用,这个引用应当指向某一个对象。后面紧跟一个代码块,这个代码块被称为“同步代码块”。这种语法的含义是,如果某一个线程想要执行代码块中的代码,必须要先获得 obj 所指向对象的互斥锁标记。也就是说,如果有一个线程 t1 要想进入同步代码块,必须要获得 obj对象的锁标记;而如果 t1 线程正在同步代码块中运行,这意味着 t1 有着 obj 对象的互斥锁标记;而这个时候如果有一个 t2 线程想要访问同步代码块,会因为拿不到 obj 对象的锁标记而无法继续运行下去。

class MyStack{
	char[] data = {'A', 'B', ' '};
	int index = 2;
	private Object lock = new Object();
	//存入数据 push和pop不会同时执行,只有一个线程可以获得lock对象的锁
	public void push(char ch){
		synchronized(lock){
		data[index] = ch;
		try{
			Thread.sleep(1000);
		}catch(Exception e){}
		index ++;
		}
	}
	//取出数据
	public void pop(){
		synchronized(lock){
			index --;
			data[index] = ' ';
		}
	}
}

在这里插入图片描述
在这里插入图片描述

同步方法

在这里插入图片描述
在这里插入图片描述

死锁

在这里插入图片描述

wait 与 notify

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值