进程
概念:进程就是正在运行的程序,它会占用对应的内存区域,由CPU进行执行与计算。
线程
概念:线程是操作系统OS能够进行运算调度的最小单位,它被包含在进程之中,是进程中的实际运作单位.
线程的三种状态
就绪 → 执行:为就绪线程分配CPU即可变为执行状态"
执行 → 就绪:正在执行的线程由于时间片用完被剥夺CPU暂停执行,就变为就绪状态
执行 → 阻塞:由于发生某事件,使正在执行的线程受阻,无法执行,则由执行变为阻塞
线程的五种状态
创建状态:线程的创建比较复杂,需要先申请PCB,然后为该线程运行分配必须的资源,并将该线程转为就绪状态插入到就绪队列中
终止状态:等待OS进行善后处理,最后将PCB清零,并将PCB返回给系统
new对应的是线程的新建状态
strat对应就绪状态,会把刚刚新建好的线程加入到就绪队列之中,之后等待os系统选中并分配CPU(线程的随机性),执行start()时,底层会自动调用我们重写的,包含自己业务的run()
通过继承thread实现多线程:
package cn.tedu.thread;
import javax.xml.stream.events.StartDocument;
//用于多线程编程实现方案:继承Thread类的方式来完成
public class TestThread1 {
public static void main(String[] args) {
//new对应的是线程的新建状态
MyThread t1=new MyThread();
MyThread t2=new MyThread();
MyThread t3=new MyThread();
MyThread t4=new MyThread();
//没有多线程抢占执行的效果,这个写法只是把代码看作是普通方法调用
// t1.run();
// t2.run();
// t3.run();
// t4.run();
//start对应就绪状态
t1.start();
t2.start();
t3.start();
t4.start();
}
}
//定义一个多线程类
class MyThread extends Thread{
@Override
public void run() {
//super.run();
for (int i = 0; i <3 ; i++) {
//getName()表示可以获取当前正在执行的线程名称
System.out.println(i+"="+getName());
}
}
}
运行结果:
0=Thread-0
0=Thread-1
1=Thread-1
2=Thread-1
1=Thread-0
2=Thread-0
0=Thread-2
1=Thread-2
2=Thread-2
0=Thread-3
1=Thread-3
2=Thread-3
thread多线程售票
package cn.tedu.tickets;
//设计多线程,4个售票窗口共计售票100
public class TestThread {
public static void main(String[] args) {
TicketThread t1 = new TicketThread("窗口一");
TicketThread t2 = new TicketThread("窗口二");
TicketThread t3 = new TicketThread("窗口三");
TicketThread t4 = new TicketThread("窗口四");
t1.start();
t2.start();
t3.start();
t4.start();
}
}
class TicketThread extends Thread{
//用static修饰后,全局只用这一个
static int tickets=10;
//添加本类的含参构造,默认的无参构造被覆盖
public TicketThread(String name) {
super(name);
}
@Override
public void run() {
while (true){
System.out.println(getName()+"="+tickets--);
if(tickets<=0){
break;
}
}
}
}
运行结果:
窗口二=10
窗口三=9
窗口一=10
窗口三=7
窗口二=8
窗口二=4
窗口二=3
窗口二=2
窗口二=1
窗口三=5
窗口一=6
窗口四=0
通过runnable接口实现多线程:
优点:
没有继承,耦合性不强,后续仍然可以继承或者实现其他接口,比较自由
可以给所有线程对象统一业务
package cn.tedu.thread;
//多线程编程实现方案二:实现runnable接口来完成
public class TestThread2 {
public static void main(String[] args) {
//创建自定义对象
MyRunable target = new MyRunable();
//创建多个线程对象,runnable没有start方法,所以需要与thread建立联系
Thread t1=new Thread(target);
Thread t2=new Thread(target);
Thread t3=new Thread(target);
Thread t4=new Thread(target);
t1.start();
t2.start();
t3.start();
t4.start();
}
}
class MyRunable implements Runnable{
@Override
public void run() {
for (int i = 0; i <3 ; i++) {
System.out.println(i+"="+Thread.currentThread().getName());
}
}
}
运行结果:
0=Thread-0
1=Thread-0
2=Thread-0
0=Thread-1
1=Thread-1
2=Thread-1
0=Thread-2
1=Thread-2
2=Thread-2
0=Thread-3
1=Thread-3
2=Thread-3
runnable实现多线程售票,int tickets前面没有static,是因为只new创建了一个对象
package cn.tedu.tickets;
public class TestRunnable {
public static void main(String[] args) {
TicketrRunnable t=new TicketrRunnable();
Thread t1=new Thread(t);
Thread t2=new Thread(t);
Thread t3=new Thread(t);
Thread t4=new Thread(t);
t1.start();
t2.start();
t3.start();
t4.start();
}
}
class TicketrRunnable implements Runnable{
//因为只new了一个对象,所有只有一个成员变量,所以不需要static修饰常量
int tickers=10;
@Override
public void run() {
while (true){
System.out.println(Thread.currentThread().getName()+"="+tickers--);
if(tickers<=0){
break;
}
}
}
}
运行结果:
Thread-0=10
Thread-0=9
Thread-0=8
Thread-0=7
Thread-0=6
Thread-0=5
Thread-0=4
Thread-0=3
Thread-0=2
Thread-0=1
Thread-1=0
Thread-2=-1
Thread-3=-2
进程和线程的关系
一个进程可以开启多个线程,其中有一个主线程来调用本进程中的其他线程,我们看到的进程的切换,切换的也是不同进程的主线程
什么是进程?什么是程序?有什么区别?
程序:数据与指令的集合,程序是静态的
进程:给程序加入了时间的概念,不同的时间进程有不同的状态
进程是动态的,就代表OS中正在运行的程序
独立性,动态性,并发性
什么是并行?什么是串行?什么是并发?
CPU:电脑的核心处理器,类似于“大脑”
串行:是指同一时刻一个CPU只能处理一件事,类似于单车道
并行:相对来说资源比较充足,多个CPU可以同时处理不同的多件事,类似于多车道
并发:相对来说资源比较紧缺,多个进程同时抢占公共资源,比如多个进程抢占一个CPU