Properties
概述:
Properties是Map集合的一个子类.Properties的键是String,值也是String.
构造:
public Properties();
方法:
public void setProperty(键,值);
public 值 getProperty(键);
public void load(Reader r); //把字符流所指向的"配置文件"中的内容,读取到Properties集合中
public void store(Writer w,String comments); //把Properties集合中的内容,写到输出流指向的文件中
多线程
相关概念
基本概念:
并发:
多个目标交替执行.
并行:
多个目标同时执行.
进程:
正在运行的程序.
线程:
程序的运行路线.
注意事项:
计算机中的程序,天然是"并发执行".
每个线程必须是完全独立.
实现多线程-继承Thread类
步骤
- 定义一个类,继承Thread类
- 重写run方法,把需要执行的代码写入run方法中.
- 创建自定义类的对象.
- 调用自定义对象的start方法,启动线程
代码
//1:定义一个类,继承Thread类
public class MyThread extends Thread{
@Override
public void run() {
//2:重写run方法,把需要执行的代码写入run方法中.
}
}
//测试类
public class Test {
public static void main(String[] args) {
//3:创建自定义类的对象.
MyThread mt = new MyThread();
//4:调用自定义对象的start方法,启动线程
mt.start();
}
}
实现多线程-实现Runnable接口
步骤
- 自定义一个类,该类实现Runnable接口
- 重写run方法,把需要执行的代码写入run方法中.
- 创建自定义类的对象
- 创建Thread类的对象,把"自定义类的对象"作为构造方法的参数
- 调用Thread类的对象start方法,启动线程
代码
//1:自定义一个类,该类实现Runnable接口
public class MyRunnable implements Runnable{
@Override
public void run() {
//2:重写run方法,把需要执行的代码写入run方法中.
}
}
//测试类
public class Test {
public static void main(String[] args) {
//3:创建自定义类的对象.
MyRunnable mr = new MyRunnable();
//4:创建Thread类的对象,把"自定义类的对象"作为构造方法的参数
Thread t = new Thread(mr);
//5:调用Thread类的对象start方法,启动线程
t.start();
}
}
实现多线程-实现Callable接口
步骤
- 自定义一个类,该类实现Callable接口
- 重写call方法,把需要执行的代码写入call方法中.
- 创建自定义类的对象
- 创建FutureTask类的对象,把"自定义类的对象"作为构造方法的参数
- 创建Thread类的对象,把"FutureTask类的对象"作为构造方法的参数
- 调用Thread类的对象start方法,启动线程
- 再调"FutureTask类的对象"的get方法,获取线程结束之后的结果。
代码
//1:自定义一个类,该类实现Callable接口,Callable接口的泛型,表示的是"该线程执行之后的结果的数据类型"
public class MyCallable implements Callable<String> {
@Override
public String call() throws Exception {
//2:重写call方法,把需要执行的代码写入call方法中.
}
}
//测试类
public class Test {
public static void main(String[] args) throws ExecutionException, InterruptedException {
//3:创建自定义类的对象
MyCallable mc = new MyCallable();
//4:创建FutureTask类的对象,把"自定义类的对象"作为构造方法的参数
FutureTask<String> ft = new FutureTask<>(mc);
//5:创建Thread类的对象,把"FutureTask类的对象"作为构造方法的参数
Thread t = new Thread(ft);
//6:调用Thread类的对象start方法,启动线程
t.start();
//7:再调"FutureTask类的对象"的get方法,获取线程结束之后的结果。
String s = ft.get();
System.out.println(s);
}
}
Thread类
public void setName(String name); //设置线程的名字
public String getName(); //获取线程的名字
public static Thread currentThread(); //获取当前线程对象
public static void sleep(long times); //让当前线程休息times毫秒.
public final void setDaemon(boolean b); //让当前线程变为守护线程(当其他线程结束时,守护线程自动结束).
线程安全问题
概述:
多个线程共同操作同一个数据,出现了"数据不准确"的现象,这种现象就被称之为"线程安全问题".
解决:
- 同步代码块
- 同步方法
- Lock锁
注意:
所谓的"解决线程安全问题",其实就是给线程加锁,简单来说,就是"我操作这个数据的时候,你不能操作,你操作的时候,我不能操作".
线程加锁
同步代码块
格式:
synchronized(锁对象){
//操作共享数据的代码
}
注意:
- 锁对象可以是任意对象.
- 锁对象必须唯一,推荐使用"当前类名.class"
- 多个线程用的"锁对象"必须是同一个
同步方法
格式:
public synchronized 返回值类型 方法名(参数){}
注意:
- 静态同步方法的锁对象是"类名.class"
- 普通同步方法的锁对象是"this"
Lock锁
语法:
private ReentrantLock rl = new ReentrantLock(); //创建"锁对象"
rl.lock() //加锁
//操作共享数据的代码
rl.unLock();//释放锁
注意:
- 该操作的锁对象就是"ReentrantLock对象".
- 释放锁的操作必须放在"finally"里边.
线程补充
死锁现象
概述:
多线程中,线程之间彼此占用对方资源,并且不释放,从而导致线程卡死的这种现象,称之为"死锁"
解决:
尽量避免锁的交叉嵌套.
生产者消费者模式
等待唤醒机制流程图
概述:
“生产者消费者模式"的核心是"多线程之间彼此叫醒对方去工作的思想”,也就是"线程间通讯"
方法:
锁对象.wait(); //当前线程等待(线程在锁上等待)
锁对象.notify(); //随机唤醒锁上等待的一个线程
锁对象.notifyAll();//唤醒锁上所有等待的线程
线程的状态
NEW:新建
RUNNABLE:可运行状态
BLOCKED:阻塞状态
WAITING:无限等待状态
TIMED_WAITING:计时等待
TERMINATED:终止
线程池
系统线程池
概述:
线程池,就是存储线程的池子.线程池可以创建和回收线程.
创建:
ExecutorService es = Executors.newCachedThreadPool(); //创建一个默认线程池.内部最多有int最大值个线程
ExecutorService es = Executors.newFixedThreadPool(int num); //创建一个线程池.内部线程最大数量为num
使用:
public Future submit(Runnable task); //提交任务.把要执行的任务交给线程池,由线程池分配线程执行
public void shutdown(); //关闭线程池
自定义线程池
概述:
ThreadPoolExecutor可以用来自定义线程池.
构造:
public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit,
BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory,
RejectedExecutionHandler handler){...}
参数:
corePoolSize: //核心线程数,不能小于0
maximumPoolSize://最大线程数,不能小于等于0,且必须大于等于核心线程数
keepAliveTime: //空闲线程最大存活时间,不能小于0
unit: //空闲线程最大存活时间单位,一般使用TimeUtil中的选项
workQueue: //任务队列(阻塞队列),该参数用于确定排队的数量,不能为null. 语法:new ArrayBlockingQueue<>(数量);
threadFactory: //创建线程的方式,一般为"Executors.defaultThreadFactory()"默认方式,不能为null
handler: //任务的拒绝策略(多余任务的处理方式)
拒绝策略:
ThreadPoolExecutor.AbortPolicy //丢弃任务并抛出RejectedExecutionException异常。是默认的策略。
ThreadPoolExecutor.DiscardPolicy //丢弃任务,但是不抛出异常 这是不推荐的做法。
ThreadPoolExecutor.DiscardOldestPolicy //抛弃队列中等待最久的任务 然后把当前任务加入队列中。
ThreadPoolExecutor.CallerRunsPolicy //调用任务的run()方法绕过线程池直接执行。