线程、进程、多线程
1、基本概念
- 多任务
- 多线程
- 很多线程是模拟出来的,真正的多线程是指多个cpu,即多核,如服务器。
- 线程
- 一个进程可以有多个线程。如视频中可以看视频,听声音,看弹幕
- main()主线程,入口
- gc() 垃圾回收线程
- 程序
- 进程
2、线程创建(Thread、Runnable、Callable,线程池)
买票时 ,继承Thread要static Runnable不要
-
Thread:
- 继承thread
- 重写run()
- 直接生成对象
- 对象.start();
- start()的作用,1.启动当前线程,2.调用当前线程的run()
- 重复调用start()会报错
- 对象.run()没有启动线程,只是调用方法而已
-
Runnable :实现接口(优先选择,没有类的单继承缺陷,可以实现多个线程共享数据)
-
实现Callable接口:
- 线程池
3、使用线程以及FileUtils下的copyURLToFile(url,name)方法
-
写一个下载类,下载类中使用了FileUtils.copyURLToFile(new URL(url),new File(name));
//下载器 class Downloader{ // 下载方法 public void downloader(String url,String name){ // FileUtils.copyURLToFile(url,name) try { FileUtils.copyURLToFile(new URL(url),new File(name)); } catch (IOException e) { e.printStackTrace(); System.out.println("出现异常"); } } }
-
写一个线程类,线程类中覆写了run()方法,以及存在url,name 两个成员变量
public class Thread1 extends Thread { private String url; private String name; public Thread1(String url,String name){ this.url=url; this.name=name; } @Override public void run() { Downloader downloader = new Downloader(); downloader.downloader(url,name); System.out.println("run方法执行,下载了文件+"+name); } public static void main(String[] args) { Thread1 thread1 = new Thread1("https://huyaimg.msstatic.com/cdnimage/game/1-MS.png","英雄联盟"); thread1.start(); } }
线程的安全问题
- 问题的提出
- 多个线程执行的不确定性引起执行结果的不稳定性
- 多个线程对账本的共享,会造成操作的不完整性,会破坏数据
- 单例模式(懒汉式)有线程安全问题
1.线程的同步
-
问题
- 卖票过程中出现重票或者错票的问题
-
原因
- 当线程操作车票的过程中,尚未完成时,其他线程参与进来,也操作车票导致出现线程问题
-
解决方法
- 当线程a在操作ticket时,其他线程不能参与进来,知道线程a操作完ticket时,其他线程才可以开始操作ticket。这种情况即使线程a出现了阻塞,也不能改变
-
在Java中,我们通过同步机制,来解决线程的安全问题
-
方式一:同步代码块
synchronize(同步监视器){
//需要被同步的代码
}
//说明:操作共享数据的代码,即为需要被同步的代码
//共享数据:多个线程共同操作的变量
//同步监视器,俗称锁。任何一个类的对象,都可以充当锁。
锁必需是同一个
-
方式二:同步方法
-
方式三:同步锁Lock(建议使用)
- private ReentrantLock lock = new ReentrantLock();
- lock.lock()
- lock.unLock()
-
2.线程的通信
线程通信的例子:先notify() 再 wait()
2个线程交叉打印
- wait():一旦执行此方法,当前线程就进入阻塞,并释放同步监视器
- notify():一旦执行此方法,就会唤醒一个被wait()的线程,如果有多个线程被wait,就唤醒优先级搞的那个.
- notifyAll():一旦执行此方法,就会唤醒所有被wait()的线程
这三个方法必须在同步代码块或者同步方法中使用
调用wait notify notifyAll 方法时都省略了this. or 类.class
wait notify notifyAll 方法的对象必须时同步监视器
wait notify notifyAll 方法时定义在Java.lang.Object下
例题:生产者和消费中的问题
面试题
1:synchronized 和 Lock的异同
- 相同:都是解决线程安全问题
- 不同:
- synchronized ,在执行完同步代码后,自动释放同步监视器
- Lock需要手动同步Lock(),手动释放unLock()s
2.sleep() 和wait()的异同
- 相同:一旦执行方法,都可以让线程进入阻塞状态
- 不同:
- 两个方法的声明位置不同:Thread类中声明sleep(),Objcet类汇总声明wait()
- 调用的要求不同:sleep()可以在任何需要的场景下调用。wait()必须使用在同步代码块中
- 如果两个方法都存在同步代码块或同步方法中,sleep()不会释放锁,wait()会释放锁
线程中的常用方法
- start() 启动线程,并调用run()
- run():线程要执行的代码写在方法里
- currentThread()静态代码,返回执行当前代码的线程
- getName() 获得线程的名字
- setName() 设置线程的名字
- yield() 释放当前cpu的执行权
- join() 在线程a中调用线程b的join(),此时线程a进入阻塞状态,直到线程b执行完,线程a才继续执行
- stop() 强制结束线程(不推荐使用)
- sleep(1000) 线程阻塞1s
- isAlive() 判断当前线程是否存活
线程的优先级
优先级只是概率,不代表一定优先级高的就先执行
- getPriority()获取优先级
- setPriority()设置优先级
- Thread.MIN_PRIORITY 10
- Thread.MAX_PRIORITY 1
- Thread.NORM_PRIORITY 5