线程基础:JDK1.5+(9)——线程新特性(中)

(接上文《线程基础:JDK1.5+(8)——线程新特性(上)》)

3、工作在多线程环境下的“计数器”:

从这个小节開始,我们将以一个“赛跑”的样例。解说JDK1.5环境下一些线程控制工具(包含Semaphore、CountDownLatch和java.util.concurrent.atomic子包),而且复习这个专题讲到的知识点:同步快、锁、线程池、BlockingQueue、Callable等。

3-1、 赛跑比赛的需求

如今您不仅能够通过我们已经介绍的知识点,实现对100米田径比赛的初赛和决赛的模拟,然后发布出比赛的冠亚季军。还能够基于这些知识,模拟机场T1和T2跑道的起降工作。这里我们一起实现前者的需求,首先来看看100米田径比赛的业务需求:

  1. 选手要參加比赛,首先就要报名。

    为了使功能足够简单,參赛选手的基本仅仅包含:姓名、起跑指数(最低速度)、參赛号三个信息。

  2. 同一个选手的状态不稳定性。也就是说某一个选手,在初赛阶段的速度可能是A,可是决赛阶段由于发挥失常,可能速度就变成了B。而这一切都是随机进行的
  3. 选手们首先进行“初赛”。全部选手的“初赛”成绩将进行汇总。成绩最好的5名选手。将參加“决赛”。“决赛”成绩最好的三名选手,将分别获得冠亚季军。并发布出来。
  4. 比赛场地仅仅有一个,总共同拥有5条跑道可供使用。

    所以不管是“初赛”还是“决赛”。同一时间參加比赛的选手都不能超过5名。

3-1-1、基本类:Player选手类

本小节兴许的内容中,我们将对跑步比赛的实现代码进行多次更改优化,可是不管实现代码怎样变化,有几个基本的模型是不会变化的:选手描写叙述和比赛结果描写叙述。

选手除了名字、參赛编号的描写叙述外,另一个“最低速度”的描写叙述,这是为了保证不管这个选手跑多少次。其状态都不会太过失常。

“最低速度”是在创建选手时,系统随机生成的。

下面是Player选手类的定义代码:

package test.thread.track;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Random;
import java.util.concurrent.Callable;
import java.util.concurrent.Semaphore;

/**
 * 这就是一个选手。
 * 为了简单起见,我们仅仅记录这个选手名字、选手编号、最低速度(创建时随机生成)。

* 当然。最为一名选手,最重要的工作就是“跑步”
 * @author yinwenjie
 */
public class Player implements Callable<Result> , Comparable<Player>{

    /**
     * 选手编号
     */
    private int number;

    /**
     * 选手的名字
     */
    private String name;

    /**
     * 最低速度
     */
    private float minSpeed;

    /**
     * 本次比赛结果
     */
    private Result result;

    /**
     * 跑道
     */
    private Semaphore runway;

    public Player(String name , int number , Semaphore runway) {
        this.name = name;
        this.number = number;
        this.runway = runway;

        // 这个最低速度设置是 8米/秒(否则就真是‘龟速’了)
        this.minSpeed = 8f;
    }

    /* (non-Javadoc)
     * @see java.util.concurrent.Callable#call()
     */
    @Override
    public Result call() throws Exception {
        try {
            // 申请上跑道
            this.runway.acquire();
            return this.doRun();
        } catch(Exception e) {
            e.printStackTrace(System.out);
        } finally {
            // 都要进入初赛结果排序(中途退赛的成绩就为0)
            this.runway.release();
        }

        // 假设运行到这里,说明异常发生了
        this.result = new Result(Float.MAX_VALUE);
        return result;
    }

    /**
     * 開始跑步
     * @return
     * @throws Exception
     */
    private Result doRun()  throws Exception {
        /*
         * 为了表现一个选手每一次跑步都有不同的状态(可是都不会低于其最低状态),
         * 所以每一次跑步,系统都会为这个选手分配一个即时速度。
         *
         * 这个即时速度不会低于其最小速度。可是也不会高于 14米/秒(否则就是‘超人’咯)
         * */
        // 生成即时速度
        float presentSpeed = 0f;
        presentSpeed = this.minSpeed * (1.0f + new Random().nextFloat());
        if(presentSpeed > 14f) {
            presentSpeed = 14f;
        }

        // 计算跑步结果(BigDecimal的使用可自行查阅资料)
        BigDecimal calculation =  new BigDecimal(100).divide(new BigDecimal(presentSpeed) , 3, RoundingMode.HALF_UP);
        float presentTime = calculation.floatValue();

        // 让线程等待presentSpeed的时间。模拟该选手跑步的过程
        synchronized (this) {
            this.wait((long)(presentTime * 1000f));
        }

        // 返回跑步结果
        this.result = new Result(presentTime);
        return result;
    }

    /**
     * @return the result
     */
    public Result getResult() {
        return result;
    }

    /**
     * @return the number
     */
    public int getNumber() {
        return number;
    }

    /**
     * @return the name
     */
    public String getName() {
        return name;
    }

    /* (non-Javadoc)
     * @see java.lang.Comparable#compareTo(java.lang.Object)
     */
    @Override
    public int compareTo(Player o) {
        /*
         * 两个选手间。还能够通过他们的result进行比較
         * 耗时越小,当然越靠前
         * */
        Result myReslut = this.getResult();
        Result targetReslut = o.getResult();

        // 假设出现了reslut为null或者targetReslut为null,说明比赛结果出现了问题
        // 当然假设真的出现这种问题,最可能的选手中途退赛了
        if(myReslut == null) {
            return 1;
        }
        if(targetReslut == null) {
            return -1;
        }

        // 耗时越少的选手,当然应该排在“成绩”队列的越前面
        if(myReslut.getTime() < targetReslut.getTime()) {
            return -1;
        } else {
            return 1;
        }
    }
}

为什么Player选手类要实现Comparable接口呢?在实现代码中,我将使用PriorityBlockingQueue队列,将选手根据其比赛成绩进行排序。为了能够保证PriorityBlockingQueue队列能够正常排序。所以须要实现该接口。

当然有的读者会说,实现Comparable接口后,使用普通的List也能够排序。可是List接口的实现类(ArrayList、LinkedList、Vector等等)并非线程安全的。它们经常使用的处理场景还是在某一个线程内进行数据线性化处理时使用。

而就眼下我们的场景来看。程序猿根本就不知道某一个选手什么时候能够跑完100米,而且多个选手跑步的处理结果都将随机的送入队列。所以保证线程安全性是需求实现中重要的一部分

当然。假设您硬是要使用传统的List也行。

能能够通过JDK提供的“同步包装器”(Collections.synchronizedList)将它变成线程安全的。但这个问题不是本小节讨论的范围。

另外。做为一个选手来说。最根本的功能就是“跑”这个动作。而且根据需求,非常明显我们须要在选手“跑完后”知道“跑”的成绩。

所以我们还须要Player类实现Callable接口,以便让选手能够跑起来。

为了模拟跑的过程和选手的状态有关,代码中使用随机数确定本次选手“跑”的速度。可是这个速度不会低于选手的“最低速度”(眼下给定的是14秒)。

3-1-2、基本类:Result比赛结果

另外一个不会变动的基本类就是Result成绩:

package test.thread.track;

/**
 * 选手某一次跑步的成绩
 * @author yinwenjie
 *
 */
public class Result {
    /**
     * 记录了本次赛跑的用时情况
     */
    private float time;

    public Result(float time) {
        this.time = time;
    }

    /**
     * @return the time
     */
    public float getTime() {
        return time;
    }

    /**
     * @param time the time to set
     */
    public void setTime(float time) {
        this.time = time;
    }
}

每一次选手“跑”的成绩都是不一样的。成绩中仅仅包含一个属性。就是跑完100米的用时情况。

3-2、Semaphore:信号量

3-2-1、基本使用

Semaphore信号量,是concurrent包的一个重要工具类。它通过申请和回收“证书”。实现多个线程对同一资源的訪问控制。详细的做法是,某个线程在訪问某个(可能出现资源抢占的)资源的时候,首先向Semaphore对象申请“证书”,假设没有拿到“证书”就一直堵塞;当拿到“证书”后。线程就解除堵塞状态,然后訪问资源;在完毕资源操作后,再向Semaphore对象归还“证书”;让我们先来看看Semaphore信号的简单演示样例:

package test.thread.semaphore;

import java.util.concurrent.Semaphore;

public class SemaphoreTest {

    public static void main(String[] args) throws Throwable {
         new SemaphoreTest().doTest();
    }

    public void doTest() {
        Semaphore semp = new Semaphore(5 , false);

        // 我们创建10个线程,并通过0-9的index进行编号
        for(int index = 0 ; index < 10 ; index++) {
            Thread semaphoreThread = new Thread(new SemaphoreRunnableNonfair(semp , index));
            semaphoreThread.start();
        }
    }

    /**
     * 測试Semaphore的非公平模式
     * @author yinwenjie
     */
    private static class SemaphoreRunnableNonfair implements Runnable {

        private Semaphore semp;

        /**
         * 编号
         */
        private Integer index;

        public SemaphoreRunnableNonfair(Semaphore semp , Integer index) {
            this.semp = semp;
            this.index = index;
        }

        @Override
        public void run() {
            try {
                System.out.println("线程" + this.index + "等待信号。

。。。

。。");
                this.semp.acquire();
                // 停止一段时间,模拟业务处理过程
                synchronized(this) {
                    System.out.println("index 为 " + this.index + " 的线程,获得信号。開始处理业务");
                    this.wait(5000);
                }
            } catch (InterruptedException e) {
                e.printStackTrace(System.out);
            } finally {
                // 最后都要释放这个信号/证书
                this.semp.release();
            }
        }
    }
}

以上代码我们创建了10个线程。分别编号为0-9(这里我们没有使用Thread自带的id,主要还是为了读者能够看得清楚)。Semaphore信号量对象中。我们放置了5个“证书”,也就是说最多同一时候能够有5个线程进行业务处理。处理完毕后向线程向Semaphore信号对象归还“证书”。以上代码的处理结果,可能例如以下图所看到的(注意。是“可能”):

线程0等待信号。。

。。。。

线程2等待信号。。

。

。。

。
index 为 2 的线程。获得信号,開始处理业务
index 为 0 的线程,获得信号,開始处理业务
线程3等待信号。

。。

。。。
index 为 3 的线程。获得信号,開始处理业务
线程4等待信号。。。。。。
index 为 4 的线程,获得信号,開始处理业务
线程5等待信号。

。。。

。。
index 为 5 的线程,获得信号,開始处理业务
线程7等待信号。。。。。。
线程8等待信号。。

。。

。。
线程6等待信号。

。。。

。。
线程9等待信号。。。。

。。
线程1等待信号。。。。。。
index 为 8 的线程,获得信号。開始处理业务
index 为 7 的线程。获得信号,開始处理业务
index 为 6 的线程,获得信号,開始处理业务
index 为 9 的线程。获得信号。開始处理业务
index 为 1 的线程。获得信号。開始处理业务

3-2-2、Semaphore的基本操作方式

为了方便读者查阅,这里我们列举了Semaphore中经常使用的操作方式

  • 申请/获取证书:

    void acquire():从此信号量获取一个许可,在Semaphore能够提供一个许可前。当前线程将一直堵塞等待。

    假设在等待过程中。当前线程收到了interrupt信号,那么将抛出InterruptedException异常。

    void acquire(permits):从此信号量获取permits个许可,在Semaphore能够提供permits个许可前,当前线程将一直堵塞等待。

    假设在等待过程中。当前线程收到了interrupt信号,那么将抛出InterruptedException异常。

    void acquireUninterruptibly():从此信号量获取一个许可,在Semaphore能够提供一个许可前,当前线程将一直堵塞等待。使用这种方法获取许可时。不会受到线程interrupt信号的影响。

    void acquireUninterruptibly(permits):从此信号量获取permits个许可。在Semaphore能够提供permits个许可前,当前线程将一直堵塞等待。使用这种方法获取许可时,不会受到线程interrupt信号的影响。

    boolean tryAcquire():从此信号量获取一个许可,假设无法获取,线程并不会堵塞在这里。

    假设获取到了许可,则返回true,其它情况返回false。

    boolean tryAcquire(permits):从此信号量获取permits个许可,假设无法获取,线程并不会堵塞在这里。

    假设获取到了许可,则返回true,其它情况返回false。

    boolean tryAcquire(int permits, long timeout, TimeUnit unit):从此信号量获取permits个许可,假设无法获取,则当前线程等待设定的时间。假设超过等待时间后。还是没有拿到许可。则解除等待继续运行。

    假设获取到了许可,则返回true,其它情况返回false。

  • 证书状态:

    int availablePermits():返回此信号量中当前可用的许可数。

    int getQueueLength():返回正在等待获取的线程的预计数目。该值仅是预计的数字,由于在此方法遍历内部数据结构的同一时候。线程的数目可能动态地变化。此方法用于监视系统状态,不用于同步控制。

    boolean hasQueuedThreads():查询是否有线程正在等待获取。注意,由于同一时候可能发生取消,所以返回 true 并不保证有其它线程等待获取许可。此方法主要用于监视系统状态。

    boolean isFair():假设此信号量的公平设置为 true,则返回 true。

  • 释放/返还证书:

    void release():释放一个许可,将其返回给信号量。

    最好将这种方法的调用,放置在finally程序块中运行。

    void release(permits):释放给定数目的许可,将其返回到信号量。

    最好将这种方法的调用,放置在finally程序块中运行。

  • fair:公平与非公平

    Semaphore一共同拥有两个构造函数,各自是:Semaphore(int permits)和Semaphore(int permits, boolean fair);permits是指由Semaphore信号量控制的“证书”数量。

    fair參数是设置这个信号量对象的工作方式。

当fair參数为true时,信号量将以“公平方式”运行。

即首先申请证书,并进入堵塞状态的线程,将有权利首先获取到证书。当fair參数为false时。信号量对象将不会保证“先来先得”。默认情况下。Semaphore採用“非公平”模式运行。

3-2-3、实现比赛场景

在介绍了Semaphore的使用方式后,如今我们就要将Semaphore增加“赛跑比赛”的代码实现中。

非常显然Semaphore在我们需求中的应用任务是:给选手使用“跑道”的证书/权利,以便让选手“跑步”,而且在选手使用完跑道后,回收跑道的使用证书/权利,给下一位选手。

......
// 这就是跑道。需求上说了仅仅有5条跑道。所以仅仅有5个permits。
Semaphore runway = new Semaphore(5);
......

这个代码片段控制着全部选手的跑步动作:仅仅有在获得跑道的使用权限后,才干运行“跑步”动作。

3-2-4、关键的一个问题

  • 什么情况下视为“初赛”、“决赛”完毕?

    那么最直观的描写叙述就是:全部报名的选手都完毕了跑步过程(中途退赛也算),才干算“初赛”完毕;“初赛”排名最靠前的前5名选手都完毕了跑步过程(中途退赛也算)才算是“决赛”完毕。

    假设没有完毕“初赛”,那么比赛进程就必须停在那里。直到“初赛”过程完毕;假设没有完毕“决赛”过程,比赛进程就必须停在那里,知道“决赛”完毕:

......
//! 仅仅有当PLAYERNAMES.length位选手的成绩都产生了,才干进入决赛。这非常重要
synchronized (this.preliminaries) {
    while(this.preliminaries.size() < OneTrack.PLAYERNAMES.length) {
        try {
            this.preliminaries.wait();
        } catch(InterruptedException e) {
            e.printStackTrace(System.out);
        }
    }
}
......
//! 仅仅有当5位选手的决赛成绩都产生了,才干到下一步:发布成绩
synchronized (this.finals) {
    while(this.finals.size() < 5) {
        try {
            this.finals.wait();
        } catch(InterruptedException e) {
            e.printStackTrace(System.out);
        }
    }
}
......
  • 怎么监控某一个选手。是否完毕了跑步过程?

在我们定义的Player选手类中,已经实现了Callable接口,而且将会在运行完毕后。返回Result结果信息。所以看选手是否完毕了跑步过程,仅仅须要监控Player的Future就能够了。

可是监控Player的Future可不能在100米比赛的主线程上进行。否则就会出现上一个选手没有跑完就不能启动下一个选手的跑步线程的情况

所以我们须要为每个选手都创建一个“监控线程”FutureThread:

/**
 * 这是计分线程,是为了保证产生比赛结果后,在计入PriorityBlockingQueue
 * 这样才有排列成绩的根据
 * @author yinwenjie
 *
 */
private class FutureThread extends Thread {

    /**
     * 选手跑步任务(Player)的运行状态对象
     */
    private Future<Result> future;

    /**
     * 跑步成绩出来后,须要操作的队列
     * (要将相应的选手增加到队列,以便根据成绩进行排序)
     */
    private PriorityBlockingQueue<Player> achievementQueue;

    /**
     * 当前进行跑步的选手
     */
    private Player player;

    public FutureThread(Future<Result> future , Player player , PriorityBlockingQueue<Player> achievementQueue) {
        this.future = future;
        this.player = player;
        this.achievementQueue = achievementQueue;
    }

    /* (non-Javadoc)
     * @see java.lang.Thread#run()
     */
    @Override
    public void run() {
        // 假设条件成立,最有可能的就是选手在比赛过程中,
        // 由于某种原因退赛了!

if(this.future == null) {
            System.out.println("选手退赛,计分为0");
        } else {
            try {
                // 假设选手没有跑完。FutureThread将堵塞在这里
                // 当然出现跑步过程中退赛。就会抛出异常
                this.future.get();
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (ExecutionException e) {
                e.printStackTrace();
            }
        }

        // 运行到这里,就说明这个选手跑完了(或者退赛了)
        // 不管什么情况,都计入队列,然后通知主线程
        this.achievementQueue.put(this.player);
        synchronized (this.achievementQueue) {
            this.achievementQueue.notify();
        }
    }
}

这样,每个选手在跑步过程中,就会有两个线程:一个用来跑步的线程:Player-Callable;另一个用来监控跑步情况。并操作成绩队列的线程:FutureThread。

3-3、完整的比赛代码

实现代码中基本的问题都攻克了,如今我们能够给出完毕的实现代码了(注意,之前已经给出的代码,就不在赘述了):

package test.thread.track;

import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.PriorityBlockingQueue;
import java.util.concurrent.Semaphore;

/**
 * 这是第一个比赛程序。
 * @author yinwenjie
 *
 */
public class OneTrack {

    private static final String[] PLAYERNAMES = new String[]{"白银圣斗士","黄金圣斗士"
        ,"青铜圣斗士","神斗士","冥斗士","哈迪斯","龟仙人","孙悟空","孙悟饭","贝吉塔","孙悟天"};

    /**
     * 报名队列(非线程安全)
     */
    private List<Player> signupPlayers = new LinkedList<Player>();

    /**
     * 初赛结果队列(有排序功能。且线程安全)
     */
    private PriorityBlockingQueue<Player> preliminaries = new PriorityBlockingQueue<Player>();

    /**
     * 决赛结果队列(有排序功能。且线程安全)
     */
    private PriorityBlockingQueue<Player> finals = new PriorityBlockingQueue<Player>();

    public void track() {
        /*
         * 赛跑分为下面几个阶段进行;
         *
         * 1、报名
         * 2、初赛。10名选手,分成两组,每组5名选手。
         * 分两次进行初赛(由于场地仅仅有5条赛道,仅仅有拿到进场许可的才干使用赛道,进行比赛)
         *
         * 3、决赛:初赛结果将被写入到一个队列中进行排序。仅仅有成绩最好的前五名选手。能够參加决赛。

*
         * 4、决赛结果的前三名将分别作为冠亚季军被发布出来
         * */

        //1、================报名
        // 这就是跑道。需求上说了仅仅有5条跑道,所以仅仅有5个permits。
        Semaphore runway = new Semaphore(5);
        this.signupPlayers.clear();
        for(int index = 0 ; index < OneTrack.PLAYERNAMES.length ; ) {
            Player player = new Player(OneTrack.PLAYERNAMES[index], ++index , runway);
            this.signupPlayers.add(player);
        }

        //2、================进行初赛
        // 这是裁判
        ExecutorService refereeService = Executors.newFixedThreadPool(5);
        for (final Player player : this.signupPlayers) {
            Future<Result> future = null;
            future = refereeService.submit(player);
            new FutureThread(future, player, this.preliminaries).start();
        }
        //! 仅仅有当PLAYERNAMES.length位选手的成绩都产生了,才干进入决赛,这非常重要
        synchronized (this.preliminaries) {
            while(this.preliminaries.size() < OneTrack.PLAYERNAMES.length) {
                try {
                    this.preliminaries.wait();
                } catch(InterruptedException e) {
                    e.printStackTrace(System.out);
                }
            }
        }

        // 3、============决赛(仅仅有初赛结果的前5名能够參见)
        for(int index = 0 ; index < 5 ; index++) {
            Player player = this.preliminaries.poll();
            Future<Result> future = null;
            future = refereeService.submit(player);
            new FutureThread(future, player, this.finals).start();
        }
        //! 仅仅有当5位选手的决赛成绩都产生了,才干到下一步:发布成绩
        synchronized (this.finals) {
            while(this.finals.size() < 5) {
                try {
                    this.finals.wait();
                } catch(InterruptedException e) {
                    e.printStackTrace(System.out);
                }
            }
        }

        // 4、============发布决赛成绩(前三名)
        for(int index = 0 ; index < 3 ; index++) {
            Player player = this.finals.poll();
            switch (index) {
            case 0:
                System.out.println("第一名:"  + player.getName() + "[" + player.getNumber() + "],成绩:" + player.getResult().getTime() + "秒");
                break;
            case 1:
                System.out.println("第二名:"  + player.getName() + "[" + player.getNumber() + "]。成绩:" + player.getResult().getTime() + "秒");
                break;
            case 2:
                System.out.println("第三名:"  + player.getName() + "[" + player.getNumber() + "]。成绩:" + player.getResult().getTime() + "秒");
                break;
            default:
                break;
            }
        }
    }

    public static void main(String[] args) throws RuntimeException {
        new OneTrack().track();
    }

    //......这里是FutureThread的代码。上面已给出了
}

下面是可能的运行结果。

“可能的运行结果”那是由于结果全然是随机的,您的运行结果可能和我给出的不一样:

第一名:龟仙人[7],成绩:7.143秒
第二名:白银圣斗士[1],成绩:7.477秒
第三名:哈迪斯[6],成绩:7.531秒

(接下文:CountDownLatch同步器、java.util.concurrent.atomic子包)

时间: 2024-08-24 10:15:43

线程基础:JDK1.5+(9)——线程新特性(中)的相关文章

Java基础:JDK1.5后的新特性:自动拆装箱,以及注意事项

首先来看一段代码: 1 Integer x = new Integer(4); 2 Integer y = 4; 在JDK1.5版本后,以上两行代码都能编译通过,那是因为JDK1.5后加入新特性,自动装箱. 第一句代码是正常的创建对象方法,创建了一个Integer包装类对象. 而第二句中,当左边的Interger类型变量指向右边的int基本类型数据时,右边的基本数据类型会自动装箱成Integer对象,即隐式执行了new Integer(4). 再来一段代码: 1 Integer x = new

jdk1.5出现的新特性----&gt;增强for循环

package cn.itcast.jdk15; import java.util.HashMap;import java.util.HashSet;import java.util.Iterator;import java.util.Map;import java.util.Set; /*jdk1.5出现的新特性---->增强for循环 增强for循环的作用: 简化迭代器的书写格式.(注意:增强for循环的底层还是使用了迭代器遍历.) 增强for循环的适用范围: 如果是实现了Iterable接

前端面试基础-html篇之H5新特性

h5的新特性(目前个人所了解)如下 语义化标签 表单新特性 视频(video)和音频(audio) canvas画布 svg绘图 地理定位 为鼠标提供的拖放API webworker (重点)Storage (重点)Websocket HTML语义化是什么? 语义化是指根据内容的结构化(内容语义化),选择合适的标签(代码语义化),便于开发者阅读和写出更优雅的代码的同时,让浏览器的爬虫和机器很好的解析. 为什么要语义化? 有利于SEO,有助于爬虫抓取更多的有效信息,爬虫是依赖于标签来确定上下文和各

Java基础之JDK1.8的接口新特性

在Java的JDK1.8中: 1.接口中使用default来修饰普通方法与使用static来修饰普通方法的意义用于避免子类重复实现同样的代码 1 package test; 2 /** 3 * 泛型的使用 4 * @author Administrator 5 * 6 */ 7 public class TestType { 8 9 public static void main(String[] args) { 10 Msg msg = new MsgImpl(); 11 msg.show()

JDK1.7的一些新特性

整理了几条对开发可能用到概率高的 1.swicth支持对String的判断:(以前只能支持Int及以下的) switch (s) { case "1": break; case "2": break; case "3": break; } 2.泛型的改善 //JDK1.7 Map<String,String> map = new HashMap<>(); //JDK1.6 Map<String,String>

java基础1.5版后新特性 自动装箱拆箱 Date SimpleDateFormat Calendar.getInstance()获得一个日历对象 抽象不要生成对象 get set add System.arrayCopy()用于集合等的扩容

8种基本数据类型的8种包装类 byte Byte short Short int Integer long Long float Float double Double char Character boolean Boolean Integer a=127; Integer b=127;//虚拟机自动装箱时进行了特殊处理,-127~128以下的自动取有过的 System.out.println(a==b);结果为true 如果是Integer a=128; Integer b=128; Sys

第6章 线程基础

6.1 线程基础 (1)线程组成:线程内核对象+线程栈(注意:进程=进程内核对象+地址空间) ①从内核角度看,线程是一个内核对象,系统用它来存储一些关于线程的统计信息(比如运行时间等) ②从编程角度看,线程是一堆寄存器状态以及线程栈的一个结构体对象.本质上可以理解为一个函数的调用器(其中的寄存器状态用于控制CPU执行,栈用于存储局部变量和函数参数及函数的返回地址)——为什么要使用线程栈的? 线程1 线程2 备注(使用线程栈的原因分析) void func1(){ int a; int b; }

Extjs5.0从入门到实战开发信息管理系统(Extjs基础、Extjs5新特性、Spring、Spring mvc、Mybatis)视频教程

Extjs5.0从入门到实战开发信息管理系统(Extjs基础.Extjs5新特性.Spring.Spring mvc.Mybatis)视频教程下载   联系QQ:1026270010 Extjs作为一款优秀的JS前端开发框架以其良好的架构.丰富的UI组件库.完善的文档和社区支持等诸多优点拥有广泛的市场应用空间,开发人员无需过多的关注HTML.CSS甚至各种常用JS算法,只需把精力放在业务逻辑上,利用各种组件的相互组合调用便可轻松而高效的开发出系统的前端页面. Extjs5在之前版本的基础上又推出

线程基础(一)

2015年自己定了个目标就是开始写写博客,所以心血来潮,我也来写写一些基础的东西. 线程,网上大把多资料,自己写也不会有什么新意.不过在自己做过的一些项目中用到很多线程相关的知识,但没有真正的去总结,去归纳的,导致到了用的时候有baidu.google(google被我朝禁了...我觉得是一种悲哀).好了,下面开始我的线程基础了 1.线程的定义 线程只由相关堆栈(系统栈或用户栈)寄存器和线程控制表TCB组成.它是系统调度的最基本单位.个人的理解是线程相当于开辟一个单元去执行特定的方法过程,就涉及

高新技术---枚举及部分JDK1.5新特性

第一讲     枚举 一.概述 这里说的枚举,不是集合vector的特有枚举迭代器,而是JDK1.5的一个新特性.之所以单独拿它开刷,是这个知识点比较重要,同时相对来说比较难理解一些. 为什么要有枚举 问题:要定义星期几或性别的变量,该怎么定义?假设用1-7分别表示星期一到星期日,但有人可能会写成int weekday = 0;或即使使用常量方式也无法阻止意外. 枚举就是要让某个类型的变量的取值只能为若干个固定值中的一个,否则,编译器就会报错.枚举可以让编译器在编译时就可以控制源程序中填写的非法