Condition

class BoundedBuffer {
final Lock lock = new ReentrantLock();
// 使用两个,可以做到通知对应的等待,不会通知到其他无关的对象
final Condition notFull = lock.newCondition();
final Condition notEmpty = lock.newCondition();
final Object[] items = new Object[100];
int putptr, takeptr, count;

public void put(Object x) throws InterruptedException {
lock.lock();
try {
while (count == items.length)
notFull.await();

items[putptr] = x;
if (++putptr == items.length) putptr = 0;
++count;

notEmpty.signal();
} finally {
lock.unlock();
}
}

public Object take() throws InterruptedException {
lock.lock();
try {
while (count == 0)
notEmpty.await();

Object x = items[takeptr];
if (++takeptr == items.length) takeptr = 0;
--count;

notFull.signal();
return x;
} finally {
lock.unlock();
}
}
}
public static void main(String[] args){
Bus bus = new Bus();

ExecutorService threadPool = Executors.newCachedThreadPool();
threadPool.execute(new MyRunnable(1, bus));
threadPool.execute(new MyRunnable(2, bus));
threadPool.execute(new MyRunnable(3, bus));
threadPool.shutdown();
}

static class MyRunnable implements Runnable{
private int idx;
private Bus bus;

public MyRunnable(int idx, Bus bus) {
this.idx = idx;
this.bus = bus;
}

@Override
public void run() {
for(int i = 0; i < 10; i++) {
switch (idx) {
case 1: bus.doOne(); break;
case 2: bus.doTwo(); break;
case 3: bus.doThree(); break;
}
}
}
}

static class Bus{
private Lock lock = new ReentrantLock();
private Condition oneCondition = lock.newCondition();
private Condition twoCondition = lock.newCondition();
private Condition threeCondition = lock.newCondition();

private int should = 1;

public void doOne(){
lock.lock();

try{
while (should != 1) toWait(oneCondition);

System.out.println("do one");
should = 2;
twoCondition.signal();
}finally {
lock.unlock();
}
}

public void doTwo(){
lock.lock();

try{
while (should != 2) toWait(twoCondition);

System.out.println("do two");
should = 3;
threeCondition.signal();
}finally {
lock.unlock();
}
}

public void doThree(){
lock.lock();

try{
while (should != 3) toWait(threeCondition);

System.out.println("do three");
System.out.println("");
should = 1;
oneCondition.signal();
}finally {
lock.unlock();
}
}

private void toWait(Condition condition){
try {
condition.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

MAC查找JDK的路径

在控制台中输入
/usr/libexec/java_home -V

即可以看见

Matching Java Virtual Machines (2):
9.0.4, x86_64: “Java SE 9.0.4” /Library/Java/JavaVirtualMachines/jdk-9.0.4.jdk/Contents/Home
1.8.0_91, x86_64: “Java SE 8” /Library/Java/JavaVirtualMachines/jdk1.8.0_91.jdk/Contents/Home

Java加密框架(JCA)简要说明

加密服务总是关联到一个特定的算法或类型,它既提供了密码操作(如Digital Signature或MessageDigest),生成或供应所需的加密材料(Key或Parameters)加密操作,也会以一个安全的方式生成数据对象(KeyStore或Certificate),封装(压缩)密钥(可以用于加密操作)。

Java Security API中,一个engine class就是定义了一种加密服务,不同的engine class提供不同的服务。下面就来看看有哪些engine class:

1)MessageDigest:对消息进行hash算法生成消息摘要(digest)。
2)Signature:对数据进行签名、验证数字签名。
3)KeyPairGenerator:根据指定的算法生成配对的公钥、私钥。
4)KeyFactory:根据Key说明(KeySpec)生成公钥或者私钥。
5)CertificateFactory:创建公钥证书和证书吊销列表(CRLs)。
6)KeyStore:keystore是一个keys的数据库。Keystore中的私钥会有一个相关联的证书链,证书用于鉴定对应的公钥。一个keystore也包含其它的信任的实体。
7)AlgorithmParameters:管理算法参数。KeyPairGenerator就是使用算法参数,进行算法相关的运算,生成KeyPair的。生成Signature时也会用到。
8)AlgorithmParametersGenerator:用于生成AlgorithmParameters。
9)SecureRandom:用于生成随机数或者伪随机数。
10)CertPathBuilder:用于构建证书链。
11)CertPathValidator:用于校验证书链。
12)CertStore:存储、获取证书链、CRLs到(从)CertStore中。

从上面这些engine class中,可以看出JCA(Java加密框架)中主要就是提供了4种服务:Digest、Key、Cert、Signature、Alogorithm。

1) 对消息内容使用某种hash算法就可以生成Digest。
2) 利用KeyFactory、KeyPairGenerator就可以生成公钥、私钥。
3) 证书中心使用公钥就可生成Cert。
4) 可以使用私钥和Digest就可以消息进行签名Signature。
5) 不论是Digest、Key、Cert、Signature,都要使用到算法Algorithm。

javadoc中{@link}与@see的简单使用以及区别

@see 标签允许用户引用其他类的文档。具体使用方式如下:
@see classname
@see fully-qualified-classname
@see fully-qualified-classname#方法名称
@see fully-qualified-classname#属性名称

我在使用的时候,发现这个只能单独一行顶头写,如果不顶头写就不管用了,没了链接的效果。
但是,{@link}这个却可以随便放。
具体使用方法和上面那个@see是一样的。

@see 让用户知道相关的内容

URL处理:解析

import android.net.Uri;

import java.net.URLDecoder;
import java.util.regex.Pattern;

public class Parser {
        protected static final Pattern PAT_QUERY =
            Pattern.compile("\\?(([a-z0-9-._~]|%[0-9a-f]{2}|[!$&'()*+,;=]|[:@]|[/?]|[/#])*)", Pattern.CASE_INSENSITIVE);

    public Parser() {
    }

    public static String getQueryParameter(String url, String key){

        try {
            int qsi = url.indexOf('?', url.indexOf(':'));
            String query = url.substring(qsi + 1);

            final String encodedKey = Uri.encode(key, null);
            final int length = query.length();
            int start = 0;
            do {
                int nextAmpersand = query.indexOf('&', start);
                int end = nextAmpersand != -1 ? nextAmpersand : length;

                int separator = query.indexOf('=', start);
                if (separator > end || separator == -1) {
                    separator = end;
                }

                if (separator - start == encodedKey.length()
                        && query.regionMatches(start, encodedKey, 0, encodedKey.length())) {
                    if (separator == end) {
                        return "";
                    } else {
                        String encodedValue = query.substring(separator + 1, end);
                        return URLDecoder.decode(encodedValue, "utf-8");
                    }
                }

                // Move start to end of name.
                if (nextAmpersand != -1) {
                    start = nextAmpersand + 1;
                } else {
                    break;
                }
            } while (true);

        }catch (Exception e){

        }

        return null;
    }

    public class Components {
        public String scheme_ = null;
        public String userinfo_ = null;
        public String host_ = null;
        public HostType hostType_ = null;
        public Integer port_ = null;
        public String[] path_ = null;
        public Boolean pathAbsolute_ = null;
        public String query_ = null;
        public String fragment_ = null;
    }

    public enum HostType {
        IPV4, IPV6, IPVFUTURE, REG_NAME
    }
}

位操作:高、中、低8位处理

public class BitwiseOperateUtil {

    /**
     * 计算结果
     * @param top 高16位
     * @param middle 中8位
     * @param mantissa 尾8位
     * @return
     */
    public static int calSourceFromMask(int top,int middle,int mantissa){
        return (top << 16) | (middle << 8) | mantissa;
    }

    /**
     * 获取指定位
     * @param n 原值
     * @param m 位数
     * @return
     */
    int getBit(int n, int m){
        return (n >> (m-1)) & 1;
    }

    /**
     * 获取高16位
     * @param value
     * @return
     */
    private int getTopSixteen(int value){
        return value >> 16;
    }

    /**
     * 获取中8位
     * @param value
     * @return
     */
    private int getMidEight(int value){
        return getMattissaEight(value >> 8);
    }

    /**
     * 获取低8位
     * @param value
     * @return
     */
    private int getMattissaEight(int value){
        return (value & 255);
    }
}

MD5:字符串和文件

import java.io.FileInputStream;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

public class Md5Utils {

    //十六进制
    private static final char HEX_DIGITS[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };

    /**
     * byte数组转换为转换为16进制
     * @param b 数据
     * @return 返回字符串
     */
    private static String toHexString(byte[] b) {
        StringBuilder sb = new StringBuilder(b.length * 2);
        for (int i = 0; i < b.length; i++) {
            sb.append(HEX_DIGITS[(b[i] & 0xf0) >>> 4]);
            sb.append(HEX_DIGITS[b[i] & 0x0f]);
        }
        return sb.toString();
    }


    /**
     * MD5对字符串校验
     * @param string
     * @return
     */
    public static String md5(String string) {
        byte[] bytes;
        try {
            bytes = MessageDigest.getInstance("MD5").digest(string.getBytes("UTF-8"));
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException("MD5 should be supported?", e);
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException("UTF-8 should be supported?", e);
        }

        return toHexString(bytes);
    }

    /**
     * 取文件MD5值
     * @param filename 文件路径
     * @return MD5值
     */
    public static String fileMD5(String filename) {
        InputStream fis;
        byte[] buffer = new byte[1024];
        int numRead = 0;
        MessageDigest md5;
        try {
            fis = new FileInputStream(filename);
            md5 = MessageDigest.getInstance("MD5");
            while ((numRead = fis.read(buffer)) > 0) {
                md5.update(buffer, 0, numRead);
            }
            fis.close();
            return toHexString(md5.digest());
        } catch (Exception e) {
            System.out.println("error");
            return null;
        }
    }
}

Zip使用:压缩和解压缩“文件”

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Enumeration;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.zip.ZipEntry;
import java.util.zip.ZipException;
import java.util.zip.ZipFile;


public class ZipFileUtil {

    private static final int BUFF_SIZE = 1024;

    private static ExecutorService mExecutor = Executors.newCachedThreadPool();

    public static void unzipFile(File file, String folderPath, UnZipProgress progress){
        mExecutor.execute(new UnZipTask(file, folderPath, progress));
    }

    public interface UnZipProgress{
        int STATUS_COMPLETE = 0;
        int STATUS_FAILURE = 1;
        void progress(int status, int progress);
    }

    private static class UnZipTask implements Runnable {

        private File mZipFile;
        private String mFolderPath;
        private UnZipProgress mUnZipProgress;

        UnZipTask(File zipFile, String folderPath, UnZipProgress progress) {
            mZipFile = zipFile;
            mFolderPath = folderPath;
            mUnZipProgress = progress;
        }

        public void unzipFile(File zipFile, String folderPath) throws ZipException, IOException {
            File desDir = new File(folderPath);
            if (!desDir.exists()) {
                desDir.mkdirs();
            }
            ZipFile zf = new ZipFile(zipFile);
            for (Enumeration<?> entries = zf.entries(); entries.hasMoreElements();) {
                ZipEntry entry = ((ZipEntry)entries.nextElement());
                if (entry.isDirectory()) {
                    continue;
                }
                InputStream in = zf.getInputStream(entry);
                String str = folderPath + File.separator + entry.getName();
                str = new String(str.getBytes(), "utf-8");
                File desFile = new File(str);
                if (!desFile.exists()) {
                    File fileParentDir = desFile.getParentFile();
                    if (!fileParentDir.exists()) {
                        fileParentDir.mkdirs();
                    }
                    desFile.createNewFile();
                }
                OutputStream out = new FileOutputStream(desFile);
                byte buffer[] = new byte[BUFF_SIZE];
                int realLength;
                while ((realLength = in.read(buffer)) > 0) {
                    out.write(buffer, 0, realLength);
                }
                in.close();
                out.close();
            }
            zf.close();
            if(mUnZipProgress != null){
                mUnZipProgress.progress(UnZipProgress.STATUS_COMPLETE, 0);
            }
        }

        @Override
        public void run() {
            try {
                unzipFile(mZipFile, mFolderPath);
            }catch (Exception e) {
                if(mUnZipProgress != null){
                    mUnZipProgress.progress(UnZipProgress.STATUS_FAILURE, 0);
                }
                e.printStackTrace();
            }
        }
    }
}

Zip使用:压缩和解压缩“字符串”

 

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;

public class ZipUtils {
   private static final String LOG_TAG = "ZipUtils";

   /*
    * 用标准的Zip包压缩数据
    */
   public static String compress(String str){
      try{
         if (str == null || str.length() == 0) {
            return str;
         }
         ByteArrayOutputStream out = new ByteArrayOutputStream();
         GZIPOutputStream gzip = new GZIPOutputStream(out);
         gzip.write(str.getBytes());
         gzip.close();
         return out.toString("ISO-8859-1");
      } catch (Exception e) {
         Logger.i(LOG_TAG, "IOException,Failed to compress1 message."+ e.toString());
      }
      return null;
   }
   
   // 解压缩
   public static String uncompress(String str){
      try{
      if (str == null || str.length() == 0) {
         return str;
      }
      ByteArrayOutputStream out = new ByteArrayOutputStream();
      ByteArrayInputStream in = new ByteArrayInputStream(str.getBytes("ISO-8859-1"));
      GZIPInputStream gunzip = new GZIPInputStream(in);
      byte[] buffer = new byte[256];
      int n;
      while((n = gunzip.read(buffer))>=0)
      {
         out.write(buffer,0,n);
      }
      return out.toString();
      }
      catch(Exception e)
      {
         Logger.i(LOG_TAG, "IOException,Failed to uncompress1 message."+ e.toString());
      }
      return null;
   }
}

 

SimpleDateFormat使用详解

SimpleDateFormat 是一个以国别敏感的方式格式化和分析数据的具体类。 它允许格式化 (date -> text)、语法分析 (text -> date)和标准化。

SimpleDateFormat函数语法:

G 年代标志符
y 年
M 月
d 日
h 时 在上午或下午 (1~12)
H 时 在一天中 (0~23)
m 分
s 秒
S 毫秒
E 星期
D 一年中的第几天
F 一月中第几个星期几
w 一年中第几个星期
W 一月中第几个星期
a 上午 / 下午 标记符
k 时 在一天中 (1~24)
K 时 在上午或下午 (0~11)
z 时区

 

public static void main(String[] args) {
SimpleDateFormat myFmt=new SimpleDateFormat(“yyyy年MM月dd日 HH时mm分ss秒”);
SimpleDateFormat myFmt1=new SimpleDateFormat(“yy/MM/dd HH:mm”);
SimpleDateFormat myFmt2=new SimpleDateFormat(“yyyy-MM-dd HH:mm:ss”);//等价于now.toLocaleString()
SimpleDateFormat myFmt3=new SimpleDateFormat(“yyyy年MM月dd日 HH时mm分ss秒 E “);
SimpleDateFormat myFmt4=new SimpleDateFormat(
“一年中的第 D 天 一年中第w个星期 一月中第W个星期 在一天中k时 z时区”);
Date now=new Date();
System.out.println(myFmt.format(now));
System.out.println(myFmt1.format(now));
System.out.println(myFmt2.format(now));
System.out.println(myFmt3.format(now));
System.out.println(myFmt4.format(now));
System.out.println(now.toGMTString());
System.out.println(now.toLocaleString());
System.out.println(now.toString());
}

2004年12月16日 17时24分27秒
04/12/16 17:24
2004-12-16 17:24:27
2004年12月16日 17时24分27秒 星期四
一年中的第 351 天 一年中第51个星期 一月中第3个星期 在一天中17时 CST时区
16 Dec 2004 09:24:27 GMT
2004-12-16 17:24:27
Thu Dec 16 17:24:27 CST 2004

位掩码 BitMask

public class Permission {  
    // 是否允许查询,二进制第1位,0表示否,1表示是  
    public static final int ALLOW_SELECT = 1 << 0; // 0001  

    // 是否允许新增,二进制第2位,0表示否,1表示是  
    public static final int ALLOW_INSERT = 1 << 1; // 0010  

    // 是否允许修改,二进制第3位,0表示否,1表示是  
    public static final int ALLOW_UPDATE = 1 << 2; // 0100  

    // 是否允许删除,二进制第4位,0表示否,1表示是  
    public static final int ALLOW_DELETE = 1 << 3; // 1000  

    // 存储目前的权限状态  
    private int flag;  

    /** 重新设置权限 */  
    public void setPermission(int permission) {  
        flag = permission;  
    }  

    /** 添加一项或多项权限 */  
    public void enable(int permission) {  
        flag |= permission;  
    }  

    /** 删除一项或多项权限 */  
    public void disable(int permission) {  
        flag &= ~permission;  
    }  

    /** 是否拥某些权限 */  
    public boolean isAllow(int permission) {  
        return (flag & permission) == permission;  
    }  

    /** 是否禁用了某些权限 */  
    public boolean isNotAllow(int permission) {  
        return (flag & permission) == 0;  
    }  

    /** 是否仅仅拥有某些权限 */  
    public boolean isOnlyAllow(int permission) {  
        return flag == permission;  
    }  
}
// 设置
permission.setPermission(Permission.ALLOW_SELECT | Permission.ALLOW_INSERT);

// 判断
permission. isAllow(Permission.ALLOW_SELECT | Permission.ALLOW_INSERT | Permission.ALLOW_UPDATE)
permission. isOnlyAllow(Permission.ALLOW_SELECT | Permission.ALLOW_INSERT)

Java 反射Api

Annotation:表示注解


AnnotatedElement:表示被注解的元素,所以不是注解。如Class、Constructor、Field、Method、Package。
GenericArrayType:表示数组类型
GenericDeclaration:声明类型变量的所有实体的公共接口
InvocationHandler:是代理实例的调用处理程序实现的接口。(真难理解/(ㄒoㄒ)/~~)
Member:成员(包括字段,方法和构造方法)
ParameterizedType:表示参数化类型
Type:是所有类型的公共接口
TypeVariable:各种类型变量的公共高级接口
WildcardType:表示通配符类型表达式,如?、?extends Number或? super Integer。

AccessibleObject:是Field、Method和Constructor对象的基类
Array:是一个工具类,提供了动态创建和访问Java数组的方法
Constructor: 提供了关于类的单个构造方法的信息以及对它的访问权限
Field
Method
Modifier
Proxy:提供用于创建动态代理类和实例的静态方法,它还是由这些方法创建的所有动态代理类的超类。
ReflectPermission:反射操作的Permission



AnnotatedElement接口是所有程序元素的父接口,所以程序通过反射获取了某个类的AnnotatedElement对象后,程序就可以调用该对象的方法来访问Annotation信息。

getAnnotation(Class): 返回程序元素上存在的、指定类型的注解。
getAnnotations():所有注解
getDeclaredAnnotations():返回自己的所有注解,不包括继承过来的。

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface FruitName {
    String value() default "";
}

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface FruitColor {
    public enum Color{ BULE,RED,GREEN};

    Color fruitColor() default Color.GREEN;
}

Modifier:

native transient volatile synchronized final static protected private public
0 0 0 0 0 0 0 0 0 0
public class MyTest {
    public int a;
    public static int b;
    public static final int c = 0;
    private int d;
}


///////////////////////////////
    public static void main(String[] args) {

        Class<?> clazz = MyTest.class;
        Field[] fields = clazz.getDeclaredFields();

        for (Field field : fields) {

            String name = field.getName();
            int modifierValue = field.getModifiers();
            String modifierStr = Modifier.toString(field.getModifiers());

            String msg = String.format("%s: 0x%08x -> %s", name, modifierValue, modifierStr);

            System.out.println(msg);
        }
    }
a: 0x00000001 -> public
b: 0x00000009 -> public static
c: 0x00000019 -> public static final
d: 0x00000002 -> private

Modifier.isPublic(field.getModifiers());
Modifier.isAbstract(field.getModifiers());