JAVA初学笔记&宋红康JAVA高级篇(其十二)

    科技2022-07-14  111

    多线程与多进程

    多线程的创建

    常用方法

    void start():启动线程,执行run()run():线程启动后执行String getName():返回线程名称void setName(String name):设置该线程名称static Thread currentThread():返回当前线程。在Thread子类中就是this,通常用于主线程和Runnable实现类static void yield():线程让步。其实就是线程异步join():线程并发堵塞static void sleep(long millis):指定单位为ms,让线程在指定时间内交出CPU控制权,时间到后才获得CPU控制权。 类似于python中的awaitstop():不保留任何未处理数据的强制关停线程boolean isAlive():bool判断线程是否存活

    方式一:继承于Thread类

    创建一个继承于Thread类的子类重写Thread类的run()创建Thread类的子类的对象通过此对象调用start() class MyThread extends Thread{ // 重修Thread的run @Override public void run(){ // 多线程执行体 System.out.println("多线程run成功"); } } class TreadTest{ public static void main(String[] args){ // 创建Thread类的子类的对象 MyThread t1 = new MyThread(); // 调用start,多线程开启 t1.start(); } }

    方式二:实现Runnable接口

    定义子类,实现Runnable接口。子类中重写Runnable接口中的run方法。通过Thread类含参构造器创建线程对象。将Runnable接口的子类对象作为实际参数传递给Thread类的构造器中。调用Thread类的start方法:开启线程,调用Runnable子类接口的run方法。

    区别

    继承Thread实现Runnable线程代码存放Thread子类run方法中线程代码存在接口的子类的run方法

    实现方式的好处

    避免了单继承的局限性多个线程可以共享同一个接口实现类的对象,非常适合多个相同线 程来处理同一份资源。

    线程优先级

    调度策略

    时间片:“拉链图式”抢占式:优先级高的线程,优先获得cpu的控制权

    Java的调度方法

    同优先级默认组成队列,使用时间片策略对高优先级,优先使用抢占式

    优先级等级

    MAX_PRIORITY:10 MIN _PRIORITY:1 NORM_PRIORITY:5

    涉及的方法

    getPriority():返回线程优先值setPriority(int newPriority):改变线程的优先级

    补充

    线程创建时继承父线程的优先级

    低优先级只是获得调度的概率低,并非一定是在高优先级线程之后才被调用

    Java中的线程分为两类:一种是守护线程,一种是用户线程

    守护线程是用来服务用户线程的,通过在start()方法前调用 thread.setDaemon(true)可以把一个用户线程变成一个守护线程。

    两者的唯一的区别是判断JVM何时离开

    线程的生命周期

    新建-就绪-运行->堵塞?->死亡并回收

    线程同步 join

    对于一些异步操作可能会脏库的操作,进行同步并发

    多个线程执行的不确定性引起执行结果的不稳定

    多个线程对账本的共享,会造成操作的不完整性,会破坏数据。

    防止新线程溢出

    class TicketDemo{ public static void main(String[] args){ Ticket t = new Ticket(); Thread t1 = new Thread(t); Thread t2 = new Thread(t); Thread t3 = new Thread(t); t1.setName("t1窗口"); t2.setName("t2窗口"); t3.setName("t3窗口"); t1.start(); t2.start(); t3.start(); } }

    Synchronized的使用方法

    方式一 synchronized(对象){ // 需要同步的代码 } 方式二 public synchronized void show (String name){ // 需要同步的代码 }

    注意:

    必须确保使用同一个资源的多个线程共用一把锁,这个非常重要,否则就 无法保证共享资源的安全

    一个线程类中的所有静态方法共用同一把锁(类名.class),所有非静态方 法共用同一把锁(this),同步代码块(指定需谨慎)

    死锁 DeadLock.java

    不同的线程分别占用对方需要的同步资源不放弃,都在等待对方放弃 自己需要的同步资源,就形成了线程的死锁出现死锁后,不会出现异常,不会出现提示,只是所有的线程都处于 阻塞状态,无法继续

    解决方法

    专门的算法、原则尽量减少同步资源的定义尽量避免嵌套同步 // 线程死锁同步 public class DeadLockTest { public static void main(String[] args) { final StringBuffer s1 = new StringBuffer(); final StringBuffer s2 = new StringBuffer(); new Thread() { public void run() { synchronized (s1) { s2.append("A"); synchronized (s2) { s2.append("B"); System.out.print(s1); System.out.print(s2); } } } }.start(); new Thread() { public void run() { synchronized (s2) { s2.append("C"); synchronized (s1) { s1.append("D"); System.out.print(s2); System.out.print(s1); } } } }.start(); } }

    锁的释放

    当前线程的同步方法、同步代码块执行结束当前线程在同步代码块、同步方法中遇到break、return终止了该代码块、 该方法的继续执行当前线程在同步代码块、同步方法中出现了未处理的Error或Exception,导 致异常结束当前线程在同步代码块、同步方法中执行了线程对象的wait()方法,当前线 程暂停,并释放锁

    不释放的锁

    线程执行同步代码块或同步方法时,程序调用Thread.sleep()、 Thread.yield()方法暂停当前线程的执行线程执行同步代码块时,其他线程调用了该线程的suspend()方法将该线程 挂起,该线程不会释放锁(同步监视器)应尽量避免使用suspend()和resume()来控制线程

    单例设计模式之懒汉式(线程安全)

    class Singleton { private static Singleton instance = null; private Singleton(){} public static Singleton getInstance(){ // 核心代码 if(instance==null){ synchronized(Singleton.class){ if(instance == null) // 核心代码 { instance=new Singleton(); } } } return instance; } } public class SingletonTest{ public static void main(String[] args){ Singleton s1=Singleton.getInstance(); Singleton s2=Singleton.getInstance(); System.out.println(s1==s2); } }
    Processed: 0.029, SQL: 8