进程:是正在运行的程序 是系统进行资源分配和调用的独立单位 每一个进程都有它自己的内存空间和系统资源。
线程:是进程中的单个顺序控制流,是一条执行路径。
单线程:一个进程如果只有一条执行路径,则称为单线程程序。
多线程:一个进程如果有多条执行路径,则称为多线程程序。
并行:多个任务同一时刻进行。
并发:多个任务同一时间间隔内进行,在一段时间内能够执行多个任务,但是这其中的某个时刻只能执行一个任务。
多线程的创建方式:继承和实现。
1.继承 Thread 类,覆写 run 方法。
2.实现 Runnable 接口,覆写 run 方法。
创建线程对象时线程对象是 Thread 类或其子类,可以使用多态。
启动线程需要调用线程对象的 start 方法,而不是直接使用 run 方法。直接调用 run 方法时,只是调用 run 方法,并没有启动线程。
优先级设置需要放在线程启动之前。优先级用 1~10 来表示,数字越大,优先级越高。
优先级在资源紧张的时候才能体现出来。
相同优先级可使用 yield 方法来让出 CPU 的执行权,但是要用在一个线程拥有时间片但是另一个相同优先级的线程没有拿到时间片的情况下。
Thread.currentThread(); 获取当前线程对象,可以用来获取 main 中的主线程等。
主线程名为 main, 其他线程名为 Thread-1,Thread-2,… 以此类推。
生命周期:
阻塞状态结束后回到就绪状态,重新排队。
stop 可能会导致死锁,一般使用标识符终止线程,比如用成员变量 flag 控制何时需要结束进程。
可以使用 join 方法实现线程合并,调用 join 方法的对象先执行线程,在哪个线程里有对象调用 join, 那么这个线程就要等到调用 join 的线程执行结束才可以继续执行。
synchronized 使用范围:成员方法,静态方法,语句块。
当某个线程访问某个对象中加了 synchronized 修饰的成员方法时,该对象中所有被 synchronized 修饰的成员方法都被锁定。静态方法同理。
给静态方法加锁是类锁,给成员方法加锁是对象锁。静态锁只影响静态,成员锁影响成员。对象之间互不影响。
可以使用 synchronized 语句块,只锁住部分代码,不用将整个方法都锁住。
为了更清晰的表达如何加锁和释放锁,JDK5 以后提供了一个新的锁对象 Lock 。
Lock 可以获得更广泛的锁定操作。
void lock():获得锁。
void unlock():释放锁。
Lock是接口,可以采用实现类ReentrantLock等实例化。
类 ReentrantLock 有一个无参构造方法:Lock lock = new ReentrantLock();。
守护线程:t.setDaemon(true);
必须在启动前设置,主线程执行完后,守护线程终止,JVM关机。
非守护线程有可能在主线程执行完后,还在执行。
生产者线程和消费者线程对同一个容器对象进行操作,使用锁和挂起唤醒机制控制操作容器中的成员。
public class ProAndCus {
public static void main(String[] args) {
Box box = new Box();
Thread proThread = new Producer(box);
Thread cusThread = new Customer(box);
proThread.start();
cusThread.start();
}
}
class Box {
private int milk = 0;
public synchronized void put() {
if (milk >= 6) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
milk++;
System.out.println("往箱子中加入了第" + milk + "瓶牛奶");
if (milk == 1) {
notifyAll();
}
}
public synchronized void get() {
if (milk <= 0) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("从箱子中取走了第" + milk + "瓶牛奶");
milk--;
if (milk == 5) {
notifyAll();
}
}
}
class Producer extends Thread{
private Box box;
public Producer(Box box) {
this.box = box;
}
@Override
public void run() {
while (true) {
box.put();
}
}
}
class Customer extends Thread{
private Box box;
public Customer(Box box) {
this.box = box;
}
@Override
public void run() {
while (true) {
box.get();
}
}
}
1.饿汉模式:该模式下在类加载时就创建了单例对象,后续不会因为多线程导致创建多个对象,所以是线程安全的。
2.懒汉模式:该模式在调用静态方法时才初始化单例对象,多线程情况下可能会导致初始化多个对象,所以需要两次判断和加锁来控制只实例化一个对象。
public class Singleton {
public static void main(String[] args) {
System.out.println(Single.getInstance());
System.out.println(Single.getInstance());
System.out.println(Single.getInstance());
System.out.println(Single.getInstance());
System.out.println(Single.getInstance());
System.out.println(Single.getInstance());
}
}
class Single {
private Single() {}
private volatile static Single single = null;
public static Single getInstance() {
if (single == null) {
synchronized(Single.class) {
if (single == null) {
single = new Single();
}
}
}
return single;
}
}
如果对您有帮助,请点赞关注支持我,谢谢!❤
如有错误或者不足之处,敬请指正!❤