JAVA笔记

来源:互联网 发布:java导出csv文件乱码 编辑:程序博客网 时间:2024/06/04 18:31

String

==与equals

  看了一部分讲解,个人理解,应该时刻记得String是一个类,并不是int等基本类型。由于类是用new在堆上创建对象,且对象的地址存在于栈中,而int等基本类型是在栈上创建。所以用“==”比较的是栈内的值,也就是说用“==”比较基本类型时,比较的是基本类型的取值,而用“==”比较类的对象时,比较的是该对象的地址。当使用“equals”比较时,比较的是堆中的取值是否相同。因此String等类在比较对象的取值时应该用equals。

实时读写文件

写properties

不使用Spring 的 Environment

  有一次在编码的时候,使用的是Spring 的Environment类,导致无法实时读取,可能是由于Environment类只是在程序启动的时候将文件读入内存,之后不再反复读取的原因。只要正常使用Properties类,在每次读取时重新打开输入流,读取之后关闭输入流即可做到实时读取。

SafeProperties properties = new SafeProperties();        try {            InputStream inputStream = new BufferedInputStream(new FileInputStream(propertiesFilePath));            properties.load(inputStream);            inputStream.close();        } catch (Exception exception) {            exception.printStackTrace();        }

只读写内存中的,不写入实体文件

  参考http://bbs.csdn.net/topics/392066071,使用如下方式:

        InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream("BaseConfig.properties");        OutputStream outputStream = new FileOutputStream(new File(this.getClass().getClassLoader().getResource("BaseConfig.properties").getFile()));

  此时加载的是class编译后的执行路径,可以做到写完数据后,下次读的时候读取到的是新数据。但从始至终,即使程序退出,也不会将数据写入到实际的文件中。例子:

public class ConfigUtil {    private static ConfigUtil instance;    private static Properties properties = null;    private ConfigUtil() {        properties = new Properties();        InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream("BaseConfig.properties");        try {            properties.load(inputStream);        } catch (IOException ex) {            Logger.getLogger(ConfigUtil.class.getName()).log(Level.SEVERE, null, ex);        }finally{            if (inputStream!=null) {                try {                    inputStream.close();                } catch (IOException ex) {                    Logger.getLogger(ConfigUtil.class.getName()).log(Level.SEVERE, null, ex);                }            }        }    }    public static ConfigUtil getInstance() {        if (instance == null) {            instance = new ConfigUtil();        }        return instance;    }    public String getValueByKey(String key) {        return (String) properties.get(key) == null ? "空" : (String) properties.get(key);    }    public void setValueByKey(String key ,String value) throws FileNotFoundException, IOException {        properties.setProperty(key, value);        OutputStream outputStream = new FileOutputStream(new File(this.getClass().getClassLoader().getResource("BaseConfig.properties").getFile()));        properties.store(outputStream, "");        outputStream.close();    }    public static void main(String[] a) throws FileNotFoundException, IOException {       ConfigUtil configTool = ConfigUtil.getInstance();       System.out.println(configTool.getValueByKey("test"));       configTool.setValueByKey("test", "33");       System.out.println(configTool.getValueByKey("test"));       configTool.setValueByKey("test", "44");       System.out.println(configTool.getValueByKey("test"));       configTool.setValueByKey("test", "55");       System.out.println(configTool.getValueByKey("test"));    }}

使用线程读入,该方法没有做到实时

  使用新的线程读入properties文件,参考http://java-my-life.iteye.com/blog/1313706

            InputStream in = new BufferedInputStream(new FileInputStream(Thread                      .currentThread().getContextClassLoader().getResource(                              "test.properties").getPath()));              

  例子

import java.io.BufferedInputStream;  import java.io.FileInputStream;  import java.io.InputStream;  import java.util.Properties;  public class Test extends Thread{      public void run()      {          while(true){              try {                  this.sleep(1000);                  readProperties();              } catch (InterruptedException e) {                  // TODO Auto-generated catch block                  e.printStackTrace();              }          }      }      private static void readProperties()      {          Properties p = new Properties();          try {              InputStream in = new BufferedInputStream(new FileInputStream(Thread                      .currentThread().getContextClassLoader().getResource(                              "test.properties").getPath()));              p.load(in);              in.close();              String name = p.getProperty("name");              String id = p.getProperty("id");              System.out.println("id=" + id + "\t name=" + name);          } catch (Exception e1) {              e1.printStackTrace();          }      }      public static void main(String[]args)      {          new Test().start();      }  }  

读properties

防止乱码

  为了防止乱码,load时可以使用InputStreamReader,然后设置charsetName为utf-8。但是使用这种方式写入时,无论是否使用SafeProperties等自定义的类,都无法保留properties文件中的注释及空行。所以尽量读写分离。

            Properties properties = new SafeProperties();            InputStream inputStream = new BufferedInputStream(new FileInputStream(propertiesFilePath));            properties.load(new InputStreamReader(inputStream, "utf-8"));            inputStream.close();

读取JAR包内的文件

获取流

  被读取的文档路径要设置成以JAR包根目录为基础的路径,如下图,environment.properties文件在JAR包根目录下的properties文件夹内,因此路径要写成”properties/environment.properties”
这里写图片描述

    InputStream inputStream = Thread.currentThread().getContextClassLoader().getResourceAsStream("properties/environment.properties");    properties.load(inputStream);    inputStream.close();

同步/互斥

Semaphore

模拟mutex

  在定义Semaphore的时候,令可用资源数量=1,即可模拟mutex。

定时任务

ScheduledExecutorService

启动

  使用ScheduledExecutorService的好处有很多,参考说明,相比于Timer具体有三处优势,1是支持多线程多任务,2是对于每个线程异常的单独处理,3是Timer执行周期任务时依赖系统时间,当系统时间变化时,会影响执行上的变化,ScheduledExecutorService基于时间的延迟,不会由于系统时间的改变发生执行变化。使用方法参考例子:

package com.effective.common.concurrent.execute;import java.text.DateFormat;import java.text.ParseException;import java.text.SimpleDateFormat;import java.util.Date;import java.util.concurrent.Executors;import java.util.concurrent.ScheduledExecutorService;import java.util.concurrent.TimeUnit;public class Schedule {    private static DateFormat dateFormat = new SimpleDateFormat("yy-MM-dd HH:mm:ss");    private static DateFormat dayFormat = new SimpleDateFormat("yy-MM-dd");    private static ScheduledExecutorService excutor = Executors.newSingleThreadScheduledExecutor();    /**     * 按指定频率周期执行某个任务 <br>     * 初始化延迟0ms开始执行,每隔5ms重新执行一次任务。     */    public void fixedRate(){        excutor.scheduleAtFixedRate(new EchoServer(), //执行线程                                    0,  //初始化延迟                                    5000, //两次开始的执行的最小时间间隔                                    TimeUnit.MILLISECONDS //计时单位                                    );    }    /**     *      */    public void fixDelay(){        excutor.scheduleWithFixedDelay(new EchoServer(),//执行线程                 0, //初始化延迟                5000, //前一次执行结束到下一次执行开始的间隔时间                TimeUnit.MILLISECONDS);    }    /**     * 每天晚上8点执行一次     */    public void dayOfDelay(String time){        ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);          long oneDay = 24 * 60 * 60 * 1000;          long initDelay  = getTimeMillis("20:00:00") - System.currentTimeMillis();          initDelay = initDelay > 0 ? initDelay : oneDay + initDelay;          executor.scheduleAtFixedRate(                  new EchoServer(),                  initDelay,                  oneDay,                  TimeUnit.MILLISECONDS);     }    /**     * 获取给定时间对应的毫秒数     * @param string "HH:mm:ss"     * @return     */    private static long getTimeMillis(String time) {                try {            Date currentDate = dateFormat.parse(dayFormat.format(new Date()) + " " +time);            return currentDate.getTime() ;        } catch (ParseException e) {            e.printStackTrace();        }        return 0;    }    public static void main(String[] args){        Schedule schedule = new Schedule();        schedule.fixedRate();        schedule.fixDelay();    }}

取消定时任务

  使用下述语句可以取消已经建立的定时任务,但是我仅仅在线程未执行或执行结束的时候用过,执行shutdown后该线程不再定时启动。若该任务线程正在执行,不知道是否可以强行终止。

    scheduledExecutorService.shutdown();

  当使用newSingleThreadScheduledExecutor()创建时,可能是由于创建的是单独的一个线程,所以在线程创建之后,线程池中已经空了。在shutdown之后,当再次启动定时任务时,会由于线程池空了而报错,异常信息:

java.util.concurrent.RejectedExecutionException: Task java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask@6386eba1 rejected from java.util.concurrent.ScheduledThreadPoolExecutor@5e5a567f[Terminated, pool size = 0, active threads = 0, queued tasks = 0, completed tasks = 0]

  因此在使用newSingleThreadScheduledExecutor()且执行了shutdown操作后,若是想再次启动定时任务,需要重新通过newSingleThreadScheduledExecutor()获取对象。

    scheduledExecutorService = Executors.newSingleThreadScheduledExecutor();

Swing

多线程中不显示界面

  下图为一个创建界面的类,当在绘制swing界面的类内部,直接在函数中使用sleep或semaphore的acquire函数时,会导致界面显示异常,仅仅剩下一个frame,无法显示加载的pannel。
这里写图片描述      这里写图片描述
  因此若需要在多个线程所控制的界面之间切换,要在线程内的run函数中写sleep,acquire等函数,这样才能正常显示。至于导致这一问题的原因,还不清楚,需要再查资料看一看,怀疑是因为sleep等导致阻塞,使得pannel无法显示。

设置图标

设置程序显示图标

  为JFrame添加图标,由于java只识别jpg、png等,不能识别ico,因此不能使用ico图片。

            Image image = Toolkit.getDefaultToolkit().getImage(iconPath + "\\mainForm.png");            frame.setIconImage(image);

窗口按钮

不关闭窗口

  当点击窗口右上角的红叉时,不关闭窗口,并执行重写的windowClosing操作。

        frame.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);        frame.addWindowListener(new WindowAdapter() {            @Override            public void windowClosing(WindowEvent e) {                JOptionPane.showMessageDialog(null, "请等待数据处理结束!");            }        });
原创粉丝点击