今日内容
1. Lock
Lock--接口
Lock提供比synchronized方法更加具有广泛性的锁操作
实现类
Java.util.concurrent.locks.ReentrantLock---官方实现Lock接口的实现类
---Lock 对象名 = new ReentrantLock()
获取锁
public void Lock()
释放锁
public void unLock()
格式
Lock 对象名 = ...(一般情况下是new ReentrantLock())
对象名.lock() ;---上锁
try{
... //完成语句
}finally{ //finally包含的代码一定会执行,除非在执行前结束jvm
对象名.unlock() ;--上面代码执行完毕后,释放锁!
}
注意
Lock和synchronized的区别
--lock可以自如地控制上锁和释放锁
--synchronized必须将上锁方法执行完毕后才能释放锁!
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
//资源类,完成电影票售票,三个窗口一共卖100张票
public class Demo implements Runnable{
//定义一个票数
private int ticket = 100 ;
//创建锁对象
Lock lock = new ReentrantLock() ;
@Override
public void run() {
//完成卖票
while (true){ //限制条件票数大于0
//上锁
lock.lock();
try{ //完成逻辑语句操作
if (ticket>50){
System.out.println(Thread.currentThread().getName()+"卖了"+(ticket--)+"张票");
}else if (ticket>0){
System.out.println(Thread.currentThread().getName()+"卖了"+(ticket--)+"张票");
}else {
System.out.println("票卖完了!");
break;
}
}finally { //完成上面语句后,finally释放资源
//释放锁
lock.unlock();
}
}
}
}
//测试,创建线程,启动线程
public class LockTest {
public static void main(String[] args) {
//创建资源类对象
Demo demo = new Demo();
//创建窗口--创建线程
Thread sell1 = new Thread(demo,"窗口1");
Thread sell2 = new Thread(demo,"窗口2");
Thread sell3 = new Thread(demo,"窗口3");
//启动线程
sell1.start();
sell2.start();
sell3.start();
}
}
2.线程池
线程池--ThreadPool
创建并存储一些可以重复利用的线程
当线程池中的线程使用完毕,不会立即释放,而是会回到线程池中,重复利用
维护成本大于普通创建线程方式!
Java.util.concurrent.Executors---工厂类!
public static ExecutorService newFixedThreadPool(int nThreads)
---创建线程池并确立里面有几个可重复线程数量
---ExecutorService-工厂服务-接口的具体实现类--public class ThreadPoolExecutor
---int nThreads-规定可重复利用线程的数量
格式
ExecutorService 线程池名 = Executor.newFixThreadPool(线程数量) ;
<T> Future<T> submit(Callable<T> task)
---提交异步任务,返回值是执行结果
---如果只是观察能否强转cpu的执行权,则可以不返回--不需要返回结果时可以返回为空!
Callable
---创建线程池,需要资源类实现的接口--类比Runnable
void shutdown()
---关闭线程池--没执行完的继续执行,后续不再进行新的任务!
//Future--不需要返回值
import java.util.concurrent.Callable;
//资源类--实现Callable接口
public class Demo implements Callable {
@Override
public Object call() throws Exception {
//完成语句--直接输出,不需要返回值,为空
for (int x = 0 ; x < 100 ; x++){
//我们并没有取名字,获得的是系统默认的名字
System.out.println(Thread.currentThread().getName()+":"+x);
}
return null;
}
}
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
//Future--不需要返回值
public class ThreadPoolTest {
public static void main(String[] args) {
//新建线程池-工程类是Executors,不是Executor!
ExecutorService threadpool = Executors.newFixedThreadPool(2) ;
//创建资源类对象
Demo demo = new Demo() ;
//通过线程池对象名调用线程--没有名字系统默认起名
threadpool.submit(demo) ;//这里可以直接用匿名对象new Demo()
//两个线程都调用
threadpool.submit(demo) ;//没有定义变量来接返回值,因为不需要或不用返回返回值
//终止线程
threadpool.shutdown();
/*
pool-1-thread-
系统默认格式-源码解决
线程池-第几个线程-线程-我们自己的输出语句
*/
}
}
//Future--需要返回值
import java.util.concurrent.Callable;
//Future--需要返回值
public class Demo implements Callable {
private Integer num ;//用来接收运算数据
//有参构造--传入要计算的数据
public Demo(Integer num){
this.num = num ;//将传进来的参数赋给成员变量
}
//定义一个结果变量用来接收结果
int sum = 0 ;
@Override
public Integer call() throws Exception {
//完成两个数的运算结果
for (int x = 0 ; x <= num ; x++){
sum += x ;
}
return sum;//返回运算结果
}
}
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class ThreadPoolTest {
public static void main(String[] args) throws ExecutionException, InterruptedException {
//创建线程池--线程为2
ExecutorService threadpool = Executors.newFixedThreadPool(2) ;
//创建资源类的对象--有参构造
Demo demo = new Demo(100);
//创建线程--传递匿名对象
Future<Integer> num = threadpool.submit(demo);
Future<Integer> num1 = threadpool.submit(new Demo(200));//匿名对象的有参构造
//获得地址值--通过get拿到具体数据
Integer result = num.get();//抛出异常
Integer result1 = num1.get();//接收数据
//输出结果
System.out.println(result);//5050
System.out.println(result1);//20100
}
}
3. Timer
Java.util.Timer
---定时器,可以执行一次或重复执行某个任务
构造方法
Timer()
---创建一个计时器
成员方法
public void cancel()
---取消定时器
void schedule(TimerTask task, Date time)
---在给定的日期时间来执行TimerTask定时任务
-->String dataStr = "2022-11-22 18:00" ;
-->日期文本---->java.util.Date
-(应用场景:引入使用io流的方式,在指定时间点上,删除指定带内容的目录里面的所有.java文件)
void schedule(TimerTask task, long delay)
---在给定多少毫秒后(延迟时间)执行这个定时任务
public void schedule(TimerTask task,long delay,long period)
---在指定延迟时间(delay)执行任务,然后每经过固定延迟时间(period)重复执行任务
schedule方法的第一个参数TimerTask--抽象类,用子类来继承并实现要完成的任务
import java.util.TimerTask;
//需要完成的任务类--继承TimerTask
public class Demo extends TimerTask {
@Override
public void run() {
System.out.println("每隔2秒输出这句话");
}
}
import java.util.Timer;
//测试Timer功能
public class TimerTest {
public static void main(String[] args) {
//创建计时器--创建Timer对象
Timer timer = new Timer() ;
//创建任务类对象--也可使用匿名对象
Demo demo = new Demo() ;
//延迟执行--隔多少秒之后执行任务
//timer.schedule(demo,2000);
//延迟执行后,每隔一段时间执行一次任务
timer.schedule(demo,2000,2000);
//停止计时器
timer.cancel();//运行代码是去掉这行
}
}
4. File
Java.io.File
描述路径形式
例子:D:\SZR\11_22\code\ClassTest1\src\Demo.java
1)File(File parent, String child)
--File file = new File(D:\SZR\11_22\code\ClassTest1\src)
---File file1 = new File(file , Demo.java)
2)File(String pathname) 推荐第二个---直接全部输出
---File file = new File(D:\SZR\11_22\code\ClassTest1\src\Demo.java)
3)File(String parent, String child)
---File file = new File(D:\SZR\11_22\code\ClassTest1\src , Demo.java)
基本功能
创建文件/文件夹
public boolean createNewFile()throws IOException
---创建文件,如果不存在,创建,返回true
public boolean mkdir()
---创建文件夹,如果存在了,则返回false;否则true
public boolean mkdirs()
---创建多级目录,当父目录不存在的时候创建
判断
public boolean isFile()--使用居多
---是否是文件
public boolean isDirectory()--使用居多
---是否是文件夹
public boolean isAbsolute()
---是否为绝对路径--从最开始到文件名
public boolean exists()
---判断文件或者目录是否存在
删除
public boolean delete()
---删除由此抽象路径名表示的文件或目录 (删除目录,目录必须为空)
注意
绝对路径
--从根目录--->文件名,一个不差
相对路径
--不写根目录-->生成的文件存在同级目录下