public class ComparatorTest {
public static void main(String[] args) {
Apple a1 = new Apple("red",120.33);
Apple a2 = new Apple("red",129.33);
Apple a3 = new Apple("red",119.33);
List<Apple> appleList = Arrays.asList(a1,a2,a3);
test1(appleList);
}
/**
* 方式1 创建类并实现Comparator
*/
public static void test1(List<Apple> appleList){
appleList.sort(new AppleComparator());
System.out.println(JSON.toJSONString(appleList));
}
/**
* 方式2 匿名内部类
*/
public static void test2(List<Apple> appleList){
appleList.sort(new Comparator<Apple>() {
@Override
public int compare(Apple o1, Apple o2) {
return o1.getWeight().compareTo(o2.getWeight());
}
});
}
/**
* 方式3 使用Lambda表达式
*/
public static void test3(List<Apple> appleList){
appleList.sort(((o1, o2) -> o1.getWeight().compareTo(o2.getWeight())));
System.out.println(JSON.toJSONString(appleList));
}
/**
* 方式4 方法3改进
*/
public static void test4(List<Apple> appleList){
//comparing中的参数是Function的实现
//其中返回的参数是用于排序的key
appleList.sort(Comparator.comparing((a -> a.getWeight())));
System.out.println(JSON.toJSONString(appleList));
}
/**
* 方式5 使用方法引用
*/
public static void test5(List<Apple> appleList){
appleList.sort(Comparator.comparing((Apple::getWeight)));
System.out.println(JSON.toJSONString(appleList));
}
}
定义一个只有一个抽象方法的接口,其实际上是一个函数式接口,可在接口前面加上@FunctionalInterface注解进行验证。
public class LambdaTestB {
public static void main(String[] args) {
Fu2 fu = a->a*5;
System.out.println(fu.add(100));
}
}
@FunctionalInterface
interface Fu2{
int add(int a);
}
注意其lambda表达式的格式应该和add()一致的函数类型
Consumer:消费型接口(void accept(T t))。有参数,无返回值 (上文forEach的参数类型就是Consumer)
Supplier:供给型接口(T get())。只有返回值,没有入参
Function
Predicate:断言型接口(boolean test(T t))。输入一个参数,输出一个boolean类型得返回值
//这个属性是用来存放 当前运行的worker数量以及线程池状态的
//int是32位的,这里把int的高3位拿来充当线程池状态的标志位,后29位拿来充当当前运行worker的数量
private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));
//存放任务的阻塞队列
private final BlockingQueue<Runnable> workQueue;
//worker的集合,用set来存放
private final HashSet<Worker> workers = new HashSet<Worker>();
//历史达到的worker数最大值
private int largestPoolSize;
//当队列满了并且worker的数量达到maxSize的时候,执行具体的拒绝策略
private volatile RejectedExecutionHandler handler;
//超出coreSize的worker的生存时间
private volatile long keepAliveTime;
//常驻worker的数量
private volatile int corePoolSize;
//最大worker的数量,一般当workQueue满了才会用到这个参数
private volatile int maximumPoolSize;
1.查看核心线程池是否已满,不满就创建一条线程执行任务,否则执行第二步。
2.查看任务队列是否已满(Blocking queue),不满就将任务存储在任务队列中,否则执行第三步。
3.查看线程池是否已满,即就是是否达到最大线程池数,不满就创建一条线程执行任务,否则就按照策略处理无法执行的任务。
Object.join():把指定的线程加入到当前线程,可以将两个交替执行的线程合并为顺序执行
比如线程B中调用了线程A的join()方法,线程A执行完成后,线程B才会开始执行
Object.wait():线程进入等待状态,进入等待状态的线程需要依赖其他线程的通知(notify/notifyAll)才能够返回到运行状态
LockSupport.park():park函数是将当前调用Thread阻塞,而unpark函数则是将指定线程Thread唤醒。与Object类的wait/notify机制相比,
park/unpark有两个优点:
① 以thread为操作对象更符合阻塞线程的直观定义
② 操作更精准,可以准确地唤醒某一个线程(notify随机唤醒一个线程,notifyAll唤醒所有等待的线程),增加了灵活性。
park是等待一个许可,unpark是为某线程提供一个许可。
如果某线程A调用park,那么除非另外一个线程调用unpark(A)给A一个许可,否则线程A将阻塞在park操作上
unpark操作可以在park操作之前
“许可”是不能叠加的,“许可”是一次性的:线程B连续调用了三次unpark函数,当线程A调用park函数就使用掉这个“许可”,如果线程A再次调用park,则进入等待状态
超时等待状态在等待状态的基础上增加了超时限制,当达到超时时间后会返回运行状态
Thread.sleep(long) 这里单位是millisconds,为了便于控制sleep的时间,可以使用
TimeUnit.SECONDS.sleep(long):TimeUnit是java.util.concurrent包下面的一个类,表示给定单元粒度的时间段,作用包括:
时间颗粒度转换
//结果:24
System.out.println( TimeUnit.DAYS.toHours( 1 ) );
//结果:3600
System.out.println( TimeUnit.HOURS.toSeconds( 1 ));
//结果是:72
System.out.println( TimeUnit.HOURS.convert( 3 , TimeUnit.DAYS ) );
延时
TimeUnit.SECONDS.sleep(long);
Object.wait(long)
Thread.join(long)
LockSupport.parkNanos(long) LockSupport.parkUntil(long)
Object.notify()
Object.notifyAll()
LockSupport.unpark(Thread)
用于修饰成员变量,告知程序任何对该变量的访问均需要从共享内存中获取,并且对于它的改变必须同步刷新回共享内存,能保证所有线程对变量访问的可见性。
过多地使用会降低程序执行的效率
用于修饰方法或者以同步块的形式来进行使用。确保多个线程在同一时刻,只能有一个线程处于方法或者同步块中,保证了线程对变量访问的可见性和排他性。
任意线程对Object的访问,首先要获取Object的监视器。如果获取失败,线程进入同步队列,状态变为Blocked,当访问Object的前驱(获得了锁的线程)释放了锁,那么该释放操作会唤醒阻塞在同步队列中的线程,使其重新尝试对监视器的获取。