进程
进程:是指一个内存中运行的应用程序,每个进程都有一个独立的内存空间和系统资源,一个应用程序可以同时运行多个进程;进程也是程序的一次执行过程,是系统运行程序的基本单位;系统运行一个程序即是一个进程从创建、运行到消亡的过程。进程是系统进行资源分配和调度的独立单位。
单cpu同一时间点只能执行一件事情,CPU高效的切换让我们觉得是同时进行的
我们在同一个进程内可以执行多个任务,每个任务就可以看成一个线程
案例:
百度云盘(一个应用程序:进程)
下载功能(可以同时下载多个文件)
进程就是正在运行的程序
进程是系统进行资源分配和调度的独立单位,每一个进程都有它自己的内存空间和系统资源。
线程
线程:线程是进程中的一个执行单元,负责当前进程中程序的执行,一个进程中至少有一个线程。一个进程中是可以有多个线程的,这个应用程序也可以称之为多线程程序。
简而言之:一个程序运行后至少有一个进程,一个进程中可以包含多个线程
在同一个进程内可以执行多个任务,而这个每个任务就是看成线程
线程是程序执行的单元,执行路径,是程序使用cpu最基本单位。
cpu 只有一个, 每次只能执行一个(线程)
一个进程有多个线程
单线程 :如果程序只有只有一条执行路径 多线程:如果程序有多条执行路径
多线程存在的意义:不是提高程序的执行速率,其实是为了提高程序的使用率。
程序的执行其实都是在抢cpu的资源,cpu的执行权。
多个线程抢夺到cpu执行权的概率更大 线程抢夺执行权具有随机性
由java命令启动jvm,启动jvm相当于启动了一个进程
接着该进程创建主线程(main)去调用main方法
jvm虚拟机的启动是单线程的还是多线程的?多线程
原因是垃圾回收线程也要启动,不然很容易就内存溢出
//1. 自定义一个类MyThread 继承Thread类
class MyThread extends Thread {
public MyThread(String name) {
super(name);
}
//2. 重写run方法
@Override
public void run() {
for (int i = 0; i < 10; i++) {
// Thread.yield(); //让出cpu 使用权
// try {
// Thread.sleep(1000);//睡眠
// } catch (InterruptedException e) {
// throw new RuntimeException(e);
// }
System.out.println(getName() + "我是最棒的:" + i);
}
}
}
public class Demo1 {
public static void main(String[] args) {
//3. 创建一个MyThread对象
MyThread t1 = new MyThread("t1");
MyThread t2 = new MyThread("t2");
//4. MyThread对象.start()
t1.start();
t2.start();
for(int i=0;i<10;i++){//主线程
System.out.println(Thread.currentThread().getName()+"我是最棒的:"+i);
}
}
}
注: run 与 start 的区别
注:new 多个MyThread对象即可。不是要理解成调用多次start了
MyThread myThread = new MyThread(“张三”); //这就是一个线程
MyThread myThread2 = new MyThread(“李四”);
myThread.start();
myThread2.start();
String getName()
返回该线程的名称。
可以在Thread的子类中直接使用
Thread.currentThread() : 得到当前线程对象
System.out.println(Thread.currentThread().getName());
分时调度:所有线程轮流使用CPU 的使用权,平均分配每个线程占用 CPU 的时间。
抢占式调度:优先让优先级高的线程使用 CPU,如果线程的优先级相同,那么会随机选择一个(线程随机性),Java使用的是抢占式调度。
设置线程的优先级:
线程优化级高,并不能让线程先执行。它还是随机的,只是概率高点
多线程好处:
充分利用CPU的资源(多进程), 多线程(为当前程序抢占CPU使用权)
简化编程模型
带来良好的用户体验
多个线程之间互不干扰
属性:
NORM_PRIORITY : 值为 5
MAX_PRIORITY : 值为 10
MIN_PRIORITY : 值为 1
构造方法:
Thread() :分配一个新的 Thread对象。。
Thread(String name) :分配一个指定名字的新的线程对象。
Thread(Runnable target) :分配一个带有指定目标新的线程对象。
Thread(Runnable target,String name) :分配一个带有指定目标新的线程对象并指定名字。
常用方法:
String getName() :获取当前线程名称。
static Thread currentThread() :返回对当前正在执行的线程对象的引用。
void setName(String name) :将此线程的名称更改为等于参数 name 。
void start() :导致此线程开始执行; Java虚拟机调用此线程的run方法。
void run() :此线程要执行的任务在此处定义代码。
static void sleep(long millis) :使当前正在执行的线程以指定的毫秒数暂停(暂时停止执行)。
int getPriority() :返回此线程的优先级。
void setPriority(int newPriority) :更改此线程的优先级。
void join() :等待这个线程死亡。
static void yield() :对调度程序的一个暗示,即当前线程愿意让出当前使用的处理器。
void interrupt() :中断这个线程。
boolean isAlive() :测试这个线程是否活着。
Thread.State getState() :返回此线程的状态。
public void run() {
// 放让线程执行代码块
for(int i=0;i<10;i++){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println(getName()+"我是最棒的:"+i);
}
}
void join() :等待这个线程死亡。
MyThread myThread = new MyThread("张三"); //这就是一个线程
MyThread myThread2 = new MyThread("李四");
myThread.start();
try {
myThread.join();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
myThread2.start();
static void yield() :对调度程序的一个暗示,即当前线程愿意让出当前使用的处理器。
public void run() {
// 放让线程执行代码块
for(int i=0;i<10;i++){
Thread.yield(); //让出cpu 使用权
System.out.println(getName()+"我是最棒的:"+i);
}
}
public final void stop (): 让线程停止,过时了,但是还可以使用。
public void interrupt ( )∶中断线程。把线程的状态终止,并抛出一个InterruptedException.
public final void setDaemon(boolean on)
将此线程标记为daemon线程或用户线程。当运行的唯一线程都是守护进程线程时,Java虚拟机将退出。
线程启动前必须调用此方法。
MyThread myThread = new MyThread("张三"); //这就是一个线程
MyThread myThread2 = new MyThread("李四");
myThread.setDaemon(true);
myThread2.setDaemon(true);
myThread.start();
myThread2.start();
// myThread.interrupt();
for(int i=0;i<10;i++){
System.out.println(Thread.currentThread().getName()+"我是最棒的:"+i);
}
//1. 创建一个Runable接口的实现类MyRunable
class MyRunabled implements Runnable {
//2. 重写run方法
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread().getName() + ":我是最棒的" + i);
}
}
}
public class Demo2 {
public static void main(String[] args) {
//3. 创建实现类MyRunable对象, myrunable
MyRunabled myRunabled = new MyRunabled();
//4. 创建Thread类的对象,把 myrunable对象作为构造参数传过去
Thread t3 = new Thread(myRunabled,"t3");
Thread t4 = new Thread(myRunabled,"t4");
t3.start();
t4.start();
for(int i=0;i<10;i++){//主线程
System.out.println(Thread.currentThread().getName()+"我是最棒的:"+i);
}
}
}
实现多线程方式:两种
方法1:Thread类
方法2:Runable 接口
问题:为什么有了方法1,还需要方法2
// 分析同票的原因
// 线程抢夺cpu 执行权时,执行的代码具有原子性
// 原子性是指最基本的代码(最小的语句)
如何解决
IllegalArgumentException