• [Java学习]多线程


    关于多进程与多线程

    使用多进程的目的:提高CPU利用率。
    使用多线程的目的:提高应用程序?利用率。
    多线程与多进程区别:进程间内存独立;同一个进程的线程间共享“堆内存和方法区内存”,栈内存是独立的,一个线程一个栈。

    JVM原理

    • Java命令启动JVM虚拟机,等于启动了一个进程,该进程会自动启动一个主线程,然后主线程去调用某个类的main方法,所以main方法执行在主线程中。
    • 单线程中,一个方法调用另一个方法,则这些方法按序压入栈中,此时JVM中只有一个栈。

    线程的创建和启动

    方法一:继承Thread类

    public class ThreadTest {
    	public static void main() {
    		//创建一个线程
    		Thread t=new Processer();
    		//启动一个线程
    		t.start();//这段代码执行瞬间结束。只是告诉JVM再分配一个栈给t线程。
    		          //run方法不需要程序员手动调用,系统线程启动后自动调用run方法。
    		
    		//t.run();//若不写t.start(),直接t.run(),将还是有一个线程,t中的方法也在主线程中执行。
    		
    		//有了多线程后,main方法结束只是说明主线程栈中没有方法栈帧了。
    		//但是其他线程(栈)中可能还有栈帧。
    		//所以main方法结束,程序可能还在运行。
    	} 
    }
    
    //定义一个线程
    public class Processor extends Thread {
    	//重写run方法
    	public void run() {
    		System.out.println("hello");
    	}
    }
    
    

    方法二:实现Runnable接口(推荐,因为一个类实现接口的同时可以保留类的继承)

    public class ThreadTest {
    	public static void main(String args[]) {
    		//创建一个线程
    		Thread t=new Thread(new Processer());
    		t.start();
    	} 
    }
    
    //定义一个线程
    public class Processer implements Runnable {
    	//重写run方法
    	public void run() {
    		System.out.println("hello");
    	}
    }
    

    线程的生命周期

    线程的调度与控制

    Java虚拟机负责线程的调度,Java使用抢占式调度模型:优先级高的线程获取的CPU时间片相对多一些。此外,线程调度模型还有分时调度模型,所有线程轮流获得CPU时间片,CPU时间片在线程间是平均分配的。

    API:获取当前线程对象、给当前线程起名、获取当前线程名称

    Thread t=Thread.currentThread();//获取当前线程对象
    t.setName("threadA");//给当前线程起名
    t.getName();//获取当前线程名
    

    优先级

    优先级:最低 1-10 最高,默认为5。
    t.setPriority(4);//设置线程优先级

    阻塞线程(sleep方法)

    Thread.sleep(5000);

    1. 注意这是一个静态方法,作用是阻塞当前线程,阻塞结束才能继续进入就绪态。由以下,t.sleep(5000)与线程t无关,作用是阻塞当前线程

    静态方法用类名调用,当用对象调用时,在运行阶段仍是类调用,与具体对象无关。

    1. 参数单位是毫秒
    2. sleep抛出InterruptedException,必须要在调用的地方处理异常。由以下有原因,若是在继承了Thread的类的重写的run方法中调用sleep方法,则只能采用try catch来处理异常;在main方法中则可以直接throw。

    覆盖的方法不能比被覆盖的方法抛出更宽泛的异常。

    中断线程的休眠:依靠异常处理机制,(InterruptedEcception)

    t.interrupt();

    终止线程较好的方法:

    在线程中设置bool变量,线程中判该变量为true才继续执行。故可在调用线程的地方更改线程的该bool变量以终止线程。

    yield方法

    Thread.yield()

    • 作用:给其他同优先级的线程让位,但让位时间不固定。
    • 该方法是一个静态方法。

    合并线程 join

    • t.join()t线程和当前线程合并,两个栈合并为一个栈。
    • join是成员方法;join有异常抛出。

    线程同步

    异步编程模型与同步编程模型

    异步编程模型:线程各自执行各自的,不需要等待对方处理完什么。
    同步编程模型:由于线程间的共享数据需要修改操作,为保证数据安全,使得一个线程执行完,另一个线程才能执行。

    两个线程共享数据方法

    通过构造函数传参,参数为共享的对象(的内存地址)。

    实现线程同步方法

    1. synchronized关键字直接作用在要同步的语句块(使用对象锁)

    把要同步的代码,放到同步语句块中。

    synchronized(同步的对象){//同步语句块
        要同步的代码
    }
    
    2. 用synchronized关键字修饰成员方法,表示this对象作为同步对象,整个成员方法都需要同步。(使用对象锁)

    原理:
    线程执行遇到synchronized关键字,就会去看同步的对象的对象锁(0/1),若能拿到对象锁,就可以执行同步语句块,否则等待,直到能拿到对象锁。
    注意,锁是加在对象上的。

    3. synchronized加在静态方法上(使用类锁)

    synchronized加在静态方法上,线程执行此方法时会找类锁(一个类只有一把类锁)。

    死锁(会写代码举例子)

    例子:
    两个线程共享两个对象,各自分别占有一个对象的锁,等待另一个对象的锁,造成死锁。
    线程中synchronized一个对象,再synchronized一个对象。

    守护线程

    • 其他所有用户线程结束,则守护线程结束。
    • 守护线程一般都是无限执行的。
    • t1.setDaemon(true);将线程设置为守护线程。
    • jvm进程启动时,启动主线程和垃圾回收器,垃圾回收器就是一个守护线程。

    定时器

    每隔一段固定时间执行一段代码。

    Timer t=new Timer();//创建定时器
    t.schedule(TimerTask task,Date firstTime,long period);//启动定时任务,此处给的声明,具体改成对应参数。
    
  • 相关阅读:
    监听器和过滤器
    jdbc电话本项目
    jdbc数据库中的增删改
    servlet实现登陆注册
    Python 数据分析基础小结
    分类模型构建
    回归模型构建
    sklearn——数据集调用及应用
    数据处理——数据集划分
    数据分析——Matplotlib图形绘制
  • 原文地址:https://www.cnblogs.com/coding-gaga/p/10580019.html
Copyright © 2020-2023  润新知