线程与进程
进程:正在运行的程序,分配内存让应用程序能够运行。
Windows系统号称多任务(可以同时运行多个应用程序)
宏观上:Windows确实是运行了多个程序
微观上:CPU快速做了切换执行任务,由于速度特别快,人感觉不到这个过程。
线程:在一个进程中负责代码的执行,就是一个进程中的执行路径。
Java程序在运行的时候,JVM会创建一个主线程,来执行代码。主线程主要负责main方法中代码的执行。
一个java程序中至少有2个线程:
一个主线程只要负责main方法中的代码执行。
一个垃圾回收器线程,负责垃圾回收。
多线程:在一个进程中多个线程同时执行不同的任务。
“同时”:单核CPU快速切换多个线程执行任务,速度特别快,人感觉不到切换。
多线程的好处:1.解决一个进程中同时执行多个任务的问题。
2.提高资源的利用率。
多线程的坏处:1.增加CPU的负担,不是线程越多越好。
2.降低了一个进程中线程的执行效率。
3.容易引发线程安全问题。
4.出现死锁现象。
Java中创建线程的两种方式:
方式一:Thread(线程类)
1.需要定义一个类来继承Thread类
2.重写Thread类中的run方法,把自定义线程的任务代码写在run方法中,每一个线程都有自己的任务代码,JVM创建的主线程的任务代码就是main方法。自定义的线程的任务代码就写在run方法中。
3.创建Thread的子类,并且调用start方法开启线程
注意点:一旦线程开启,会默认执行线程对象中的run方法,但是千万不要自己直接调用run方法,如果直接调用了run方法,就和普通方法没有区别。
线程如果执行sleep wait方法,线程会处于阻塞状态。Sleep,如果超过了睡眠时间会立马进入等待运行状态。如果是wait需要通过其他线程来唤醒。
//线程中常用的方法。
Thread(String name) 初始化线程的名字
getName() 返回线程的名字
setName(String name) 设置线程对象名
sleep() 线程睡眠指定的毫秒数。
getPriority() 返回当前线程对象的优先级 默认线程的优先级是5
setPriority(int newPriority) 设置线程的优先级 虽然设置了线程的优先级,但是具体的实现取决于底层的操作系统的实现(最大的优先级是10 ,最小的1 , 默认是5)。
currentThread() 返回CPU正在执行的线程的对象
Eg:System.out.println("当前线程对象"+Thread.currentThread());
System.out.println("获取主线程的优先级:"+对象.getPriority());
try{
Thread.sleep(500);
}catch(InterruptedException e){
e.printStackTrace();
}
java给线程加锁 :
方式一:同步代码块
//锁对象可以是任意一个java中的对象
//java中的任意一个对象 都会有一个对象的状态 ,就可以通过对象的状态来作为锁的一个标识符。
// statue = 0 表示锁是关闭 statue = 1 表示锁打开。
synchronized (锁对象) {
}
同步代码块的使用注意点 :
1.任意一个对象都可以做锁对象
2.如果你在同步代码块中调用了sleep方法 ,不会释放锁对象
3.只有真正存在线程安全的时候才需要使用同步代码块,否则会降低执行效率
4.多线程操作锁对象必须是唯一的 ,否则无效
出现线程安全的问题根本原因:
1.存在两个或两个以上的线程。并且线程之间共享着一个资源。
2.多个语句操作了共享资源
方式二:同步函数 :用关键字synchronized 修饰函数
同步函数是否有锁对象 : 有的。
同步函数的使用注意点:
1.如果是一个非静态的函数,同步函数的锁对象就是调用方法的对象(this对象),如果是一个静态函数同步函数的锁对象
是当前函数所属类的字节码文件(Class对象)
2.同步函数的锁对象固定,不能够自己来指定。
3.同步函数是同步整个函数的代码。
推荐使用 : 同步代码块。
原因 :
1.同步代码块的锁对象可以由我任意指定,同步函数是固定的。
2.同步代码块可以控制被同步的范围,同步函数必须是整个函数的所有代码都被同步
代码同步是可以解决线程安全问题
但是如果使用不当会导致线程死锁问题:
A线程等B线程完成, B线程又在等A线程 结果两个人就一直等下去了 ,这个时候就造成了线程死锁。
线程死锁不一定会出现,有可能会出现。
死锁现象的解决方案 : 没有方案 ,尽量避免发生。
线程的通讯:一个线程完成自己的任务,去通知另外一个线程去完成另外一个任务。
wait(); 等待 如果线程执行了wait方法 ,那么该线程就会处于一个等待状态,等待状态的线程必须要通过其他线程来调用
notify()方法来唤醒。
notify();唤醒 随机唤醒线程池中的一个线程。
notifyAll(); 唤醒所有等待的线程
生产者和消费者。
wait和notify的使用注意点 :
1.wait方法和notify方法是属性Object对象
2.wait方法和notify方法必须在同步线程中执行
3.wait方法和notify方法必须有锁对象来调用