定时器
带动整个计算机硬件的发展的核心关键性技术就是时钟。所以在企业开发中定时操作常常成为开发重点。而在JDK本身也支持这些定时调度的处理操作,这些操作不会直接使用。还是和多线程有关。
假如想要定时调度处理操作,须要两个类
package com.day14.demo;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;
class MyTask extends TimerTask{
@Override
public void run() {
// TODO Auto-generated method stub
System.out.println(new SimpleDateFormat("YYYY-MM-dd HH:mm:ss.SSS").format(new Date()));
}
}
public class TaskDemo {
public static void main(String[] args) {
Timer timer = new Timer();
timer.schedule(new MyTask(), 1000,2000);
}
}
复制代码
UUID类
UUID类是按照你当前的地址还有时间戳手动生成一个几乎不会重复的字符串。
package com.day14.demo;
import java.util.UUID;
public class UUIDDemo {
public static void main(String[] args) {
UUID uuid = UUID.randomUUID();
System.out.println(uuid);
}
}
复制代码
之后再文件上传等类似的操作中通过UUID类来进行简单的文件名称,以避免重名的问题。
Base64加密处理
Base64是一种数据加密算法,使用整个算法可以使我们的数据进行安全处理。假如要想进行加密处理可以使用两个:加密器、解密器。
加密处理
package com.day14.demo;
import java.util.Base64;
public class Base64Demo {
public static void main(String[] args) {
String msg = "123456";
String emsg = Base64.getEncoder().encodeToString(msg.getBytes());
System.out.println("加密:" + emsg);
byte[] decode = Base64.getDecoder().decode(emsg);
System.out.println("解密:" + new String(decode));
}
}
复制代码
多次加密
package com.day14.demo;
import java.util.Base64;
public class Base64Demo {
public static void main(String[] args) {
String msg = encode("123456");
String emsg = encode(encode(encode(msg)));
System.out.println("加密:" + emsg);
byte[] decode = Base64.getDecoder().decode(emsg);
System.out.println("解密:" + new String(decode));
}
public static String encode(String code){
return Base64.getEncoder().encodeToString(code.getBytes());
}
}
复制代码
还有一个做法就是种子树
package com.day14.demo;
import java.util.Base64;
public class Base64Demo {
public static void main(String[] args) {
String sed = encode("zsr--rsz");
String msg = "123456"+sed;
String emsg = encode(msg);
System.out.println("加密:" + emsg);
byte[] decode = Base64.getDecoder().decode(emsg);
System.out.println("解密:" + new String(decode));
}
public static String encode(String code){
return Base64.getEncoder().encodeToString(code.getBytes());
}
}
复制代码
必须保证宽度,之后的开发将Base64和MD5一起开发,宽度是32位。
ThreadLocal类
TheadLocal类不承继Thread类,也不实现Runable插口,ThreadLocal类为每一个线程都维护了自己独有的变量拷贝。每位线程都拥有自己独立的变量。
ThreadLocal采用了“以空间换时间”的形式:访问并行化,对象独享化。后者仅提供一份变量,让不同的线程排队访问,而前者为每一个线程都提供了一份变量,因而可以同时访问而互不影响。
ThreadLocal的实现是这样的:每位Thread维护了一个ThreadLocalMap映射表,这个映射表的key是ThreadLocal实例本身。Value是真正须要储存的变量。也就是说,ThreadLocal本身并不存储值,它只是作为一个key来让线程从ThreadLocalMap获取value。注意,ThreadLocalMap是使用ThreadLocal的弱引用作为key的,弱引用的对象在GC时会被回收。
通过给方式传递参数,调用两个线程输出不同的信息
package com.day14.demo;
class Message{
private String note;
public String getNote() {
return note;
}
public void setNote(String note) {
this.note = note;
};
}
class GetMessage{
public void print(Message msg){
System.out.println(Thread.currentThread().getName() + msg.getNote());
}
}
public class ThreadLocalDemo {
public static void main(String[] args) {
new Thread(()->{
Message message = new Message();
message.setNote("Hello,world!!");
new GetMessage().print(message);
},"用户A").start();
new Thread(()->{
Message message = new Message();
message.setNote("Hello,world!!zsr");
new GetMessage().print(message);
},"用户B").start();
}
}
复制代码
然而我如今的需求是不希望通过传递传输给GetMessage的print方式,还希望实现相同的功能。
package com.day14.demo;
class Message{
private String note;
public String getNote() {
return note;
}
public void setNote(String note) {
this.note = note;
};
}
class GetMessage{
public void print(){
System.out.println(Thread.currentThread().getName() + MyUtil.message.getNote());
}
}
class MyUtil{
public static Message message;
}
public class ThreadLocalDemo {
public static void main(String[] args) {
new Thread(()->{
Message msg = new Message();
msg.setNote("Hello,world!!");
MyUtil.message = msg;
new GetMessage().print();
},"用户A").start();
new Thread(()->{
Message msg = new Message();
msg.setNote("Hello,world!!zsr");
MyUtil.message = msg;
new GetMessage().print();
},"用户B").start();
}
}
复制代码
我们发觉两个线程的内容并没有同步输出,所以我们会想到通过ThreadLocal类来解决此数据不同步的问题。
public class ThreadLocal extends Object
复制代码
这个类上面有几个重要的方式:
借助ThreadLocal来解决当前我问题
package com.day14.demo;
class Message{
private String note;
public String getNote() {
return note;
}
public void setNote(String note) {
this.note = note;
};
}
class GetMessage{
public void print(){
System.out.println(Thread.currentThread().getName() + MyUtil.get().getNote());
}
}
class MyUtil{
private static ThreadLocal tl = new ThreadLocal();
public static void set(Message msg){
tl.set(msg);
}
public static Message get(){
return tl.get();
}
}
public class ThreadLocalDemo {
public static void main(String[] args) {
new Thread(()->{
Message msg = new Message();
msg.setNote("Hello,world!!");
MyUtil.set(msg);
new GetMessage().print();
},"用户A").start();
new Thread(()->{
Message msg = new Message();
msg.setNote("Hello,world!!zsr");
MyUtil.set(msg);
new GetMessage().print();
},"用户B").start();
}
}
复制代码
这样我们就解决了数据不同步的问题了。
IO—File类基本操作
假如要想学好IO,必需要清楚具象类、IO的操作部份把握两个代码模型。IO的核心组成五个类(File、OutputStream、InputStream、Writer、Reader)一个插口(Serializable)。
再java.io是一个与文本本身操作有关的程序(创建、删除、信息取得---)
假如要想使用File类操作文件的话,这么肯定要通过构造方式实例化File类对象,而实例化File类对象的过程之中主要使用以下两种构造方式:
方式一:publicFile(Stringpathname);技巧二:publicFile(Fileparent,Stringchild).
文件的基本操作,主要有以下几种功能:
创建新文件
package com.day14.demo;
import java.io.File;
import java.io.IOException;
public class FileDemo {
public static void main(String[] args) throws IOException {
File file = new File("f:\hello.txt");
file.createNewFile();
}
}
复制代码
假如文件存在进行删掉,不存在进行创建
package com.day14.demo;
import java.io.File;
import java.io.IOException;
public class FileDemo {
public static void main(String[] args) throws IOException {
File file = new File("f:\hello.txt");
if(file.exists()){//文件存在
file.delete();
}else{//文件不存在
file.createNewFile();//创建文件
}
}
}
复制代码
本程序操作就表示假如文件存在则删掉,假若不存在则创建一个新的文件,此时基本功能是实现了linux windows,不过这个程序此时存在三个问题:
问题一:关于路径的分隔符
在windows操作之中,使用“”作为路径分隔符,而在Linux系统下使用“/”作为路径分隔符,而实际的开发而言,大部份情况下会在windows中做开发,而后将项目布署在Linus,这么此时,路径的分隔符都须要进行更改,这样实在是粤语麻烦,因此在File类之中提供了一个常量:publicstaticfinalStringseparator(根据Java的命名规范来讲,对于全局常量应当使用小写字母的形式定义,而此处使用的是大写,是由Java的发展历史所带来的问题)。
//由不同的操作系统的JVM来决定最终的separator是什么内容File file = new File("f:" + File.separator + "hello.txt");
复制代码
问题二:是有可能会出现的延后问题
发觉程序执行完成以后,对于文件的创建或则是删掉是会存在一些操作上的延后linux驱动定时器,假如现今假定先删掉了一个文件,而后立即判定此文件是否存在,这么可能得到的结果就是错误的(为true),一位所有的*.class文件都要通过JVM与操作系统间接操作,这样就有可能会出现延后的问题。
问题三:目录问题
之前进行文件创建的时侯都是在根目录下创建完成的,假如说现今要创建的文件有目录呢?诸如,如今要创建一个f:hellohello.txt文件linux驱动定时器,而此时在执行程序的时侯hello目录不存在,这个时侯执行的话还会出现错误提示:
Exception in thread "main" java.io.IOException: 系统找不到指定的路径。
复制代码
由于现今目录不存在,所以不能创建,这么这个时侯必须首先判定要创建文件的父路径是否存在,倘若不存在应当创建一个目录,然后再进行文件的创建,而要想完成这样的操作,须要一下几个方式支持:
找到一个指定文件的父路径:publicFilegetParentFile();
创建目录:publicbooleanmldirs()。
package com.day14.demo;
import java.io.File;
import java.io.IOException;
public class FileDemo {
public static void main(String[] args) throws IOException {
//由不同的操作系统的JVM来决定最终的separator是什么内容
File file = new File("f:" + File.separator +"hello" + File.separator + "hello.txt");
if(!file.getParentFile().exists()){//父目录
file.getParentFile().mkdirs();//创建父目录
}
if(file.exists()){//文件存在
file.delete();
}else{//文件不存在
file.createNewFile();//创建文件
}
}
}
复制代码
之后在任何的java.io.File类开发过程之中,都一定要考虑文件目录的问题。
取得文件信息
在File类之中还可以通过以下的方式取得一些文件的基本信息:
方式名称
描述
publicStringgetName()
取得文件的名称
publicbooleanisDirectory()
给定的路径是否为文件夹
publicbooleanisFile()
给定的路径是否是文件
publicbooleanisHidden()
是否是隐藏文件
publiclonglastModified()
文件的最后一次更改日期
publiclonglength()
取得文件大小,是以字节为单位返回的。
获取文件的大小信息以及核心信息
package com.day14.demo;
import java.io.File;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.Date;
class MyMath{
public static double round(double num, int scale){
return Math.round(num * Math.pow(10, scale)) / Math.pow(10, scale);
}
}
public class FileDemo2 {
public static void main(String[] args) {
File file = new File("f:" + File.separator + "701_03_支付宝沙箱使用.avi");
if(file.exists() && file.isFile()){
System.out.println("1文件大小为:" + MyMath.round(file.length() / (double) 1024 / 1024, 2));
System.out.println("最后一次修改日期:"+ new SimpleDateFormat("YYYY-MM-dd HH:mm:ss").format(new Date(file.lastModified())));
System.out.println("2文件大小为:" + new BigDecimal(file.length() / (double)1024 /1024).divide(new BigDecimal(1), 2, BigDecimal.ROUND_HALF_UP).doubleValue());
}
}
}
复制代码
列举目录内容:publicFile[]listFiles()linux安装教程,此方式将目录中的所有文件以File对象字段的形式返回;
列举目录的所有结构
package com.day14.demo;
import java.io.File;
import java.util.Arrays;
public class FileDemo3 {
public static void main(String[] args) {
File file = new File("f:" + File.separator);
if(file.exists() && file.isDirectory()){
File[] listFiles = file.listFiles();
System.out.println(Arrays.toString(listFiles));
}
}
}
复制代码
综合案例:目录列表
如今希望把一个目录下的全部文件都列下来,这么这些情况下只能采用递归:由于列举一个目录下的全部文件或着文件夹以后,假如发觉列举的内容是文件夹,则应当向后继续列举。
列举指定目录下的所有文件
package com.day14.demo;
import java.io.File;
public class FileListDemo {
public static void main(String[] args) {
File file = new File("f:" + File.separator);
list(file);
}
public static void list(File file){
if(file.isDirectory()){
File[] files = file.listFiles();
if(files != null){
for (int i = 0; i < files.length; i++) {
list(files[i]);//继续列出
}
}
}
System.out.println(file);
}
}
复制代码
线程阻塞问题
现今代码都在main线程下执行,假如该程序执行完成后才会继续执行下一条句子,要想解决这些历时的问题。最好形成一个新的线程进行列举。
package com.day14.demo;import java.io.File;public class FileListDemo { public static void main(String[]