https://github.com/Philbenzy/Java-question-100/tree/main/day23
(1)线程与进程
进程:系统中运行的应用程序;
线程:应用程序为了提高自身的执行效率,是进程执行的单元,多线程有助于提高程序使用率;
进程与线程之间,举个例子帮助理解,就像是手掌上的5根指头,在打字、拿东西时提高了我们的执行效率
运行原理:使用Java命令开启JVM,之后JVM启动进程,进程又会启动一个主线程;
JVM启动:最低启动了两个线程,主线程与垃圾回收线程
二者都需要重写run()方法,在主线程中使用start()方法启动;
**问题:**run()与start()方法的区别
如果只调用了run方法,那么与普通执行没有区别,start方法会开启多线程
代码实现:
// 方式一:继承Thread类
public class MyThread extends Thread {
@Override
public void run() {
System.out.println("方法开始执行!");
for (int x = 0; x < 10; x++) {
System.out.println(getName()+" x:" + x);
}
System.out.println("方法执行完毕");
}
}
public class MyThreadDemo {
public static void main(String[] args) {
MyThread mt1 = new MyThread();
MyThread mt2 = new MyThread();
mt1.start();
mt2.start();
}
}
// 方式2:实现Runable接口
public class MyRunnable implements Runnable {
@Override
public void run() {
for (int x = 0; x < 100; x++) {
System.out.println(Thread.currentThread().getName() + ":" + x);
}
}
}
public class MyRunnableDemo {
public static void main(String[] args) {
MyRunnable my = new MyRunnable();
// Thread(Runnable target, String name)
Thread t1 = new Thread(my, "进程1");
Thread t2 = new Thread(my, "进程2");
t1.start();
t2.start();
}
}
Java执行抢占制线程调度
优先级方面,使用setPriority(int a)设置优先级
JVM默认a=5,MAX =10,min=1;
线程是否守护的意义在于,如果当前所执行的所有线程都属于守护线程,则线程退出;
在该线程终止后,其他线程才开始执行
使用sleep方法使线程睡眠,线程进入阻塞状态
在run方法内写入该礼让方法,表示暂停当前正在执行的线程对象,执行其他线程,让多个线程执行更加和谐
生命周期的组成被分为:创建、就绪、运行、阻塞、死亡
(1)案例
public class SealTicket implements Runnable{
private int ticket = 100;
private Object obj = new Object();
@Override
public void run() {
while (true) {
synchronized (obj) {
if (ticket > 0) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + ": 正在出售第 " + ticket + " 张票...");
ticket--;
} else {
System.out.println("Sale Out");
System.exit(0);
}
}
}
}
}
public class SynDemo {
public static void main(String[] args) {
SealTicket st= new SealTicket();
Thread t1 = new Thread(st,"window1");
Thread t2 = new Thread(st,"window2");
Thread t3 = new Thread(st,"window3");
Thread t4 = new Thread(st,"window4");
t1.start();
t2.start();
t3.start();
t4.start();
}
}
(2)问题
以上的案例不会出现卖负票,同票多次的问题,是因为需要执行的代码使用了synchronized关键字修饰;
那么之前的问题该怎么解释?
我们假设第一个线程准备对余票数量进行修改,此时另一线程读到了还未修改的余票数量,可能会出现票数的重复与负数。
(1)是否有多线程环节
(2)是否有共享数据
(3)是否有多条语句操作共享数据
锁:synchronized(Object obj){代码块},其中,所的创建的锁对象,锁内需要一个对象保证多个线程使用一个共同的锁对象;
使用synchronized关键字修饰需要同步的代码
在方法上声明关键词synchronized,此时锁对象为this
使用唯一的class文件创建锁对象,synchronized(xxx.class)
目前,线程安全的类有三个
注意:Vector一般不会使用,一般使用「public static
List