精华内容
下载资源
问答
  • 由此我产生了以下几个疑问: 1,JAVA的线程是抢占式的,但又遵守支持时间片的操作系统的时间片调度,那么这里的抢占与时间片轮换之间又有怎样的关系,是怎么协调的? 2,每个线程的时间片分配大小是否相等? 3,...

    如下程序publicclassThreadTest{publicstaticvoidmain(String[]args){MyThreadth=newMyThread();newThread(th).start();newThread(th).start();newThread(th).start();newThread(th)....

    如下程序

    public class ThreadTest {

    public static void main(String[] args) {

    MyThread th=new MyThread();

    new Thread(th).start();

    new Thread(th).start();

    new Thread(th).start();

    new Thread(th).start();

    }

    }

    class MyThread implements Runnable {

    int tickets = 20;

    Object obj = new Object();

    public void run(){

    while(true){

    synchronized(obj){

    if(tickets > 0){

    try {

    Thread.sleep(10);

    } catch (InterruptedException e) {

    // TODO 自动生成 catch 块

    e.printStackTrace();

    }

    System.out.println("现在卖第"+tickets+"张 买卖票窗口:"+Thread.currentThread().getName());

    tickets--;

    }

    else{

    System.out.println("窗口"+Thread.currentThread().getName()+"票已经卖完");

    break;

    }

    }

    }

    }

    }

    由时间片分配可知运行的结果应该是各个线程运行同样的时间,卖出同样的票啊,但结果却是这样的

    现在卖第20张 买卖票窗口:Thread-0

    现在卖第19张 买卖票窗口:Thread-3

    现在卖第18张 买卖票窗口:Thread-3

    现在卖第17张 买卖票窗口:Thread-3

    现在卖第16张 买卖票窗口:Thread-3

    现在卖第15张 买卖票窗口:Thread-3

    现在卖第14张 买卖票窗口:Thread-2

    现在卖第13张 买卖票窗口:Thread-2

    现在卖第12张 买卖票窗口:Thread-2

    现在卖第11张 买卖票窗口:Thread-2

    现在卖第10张 买卖票窗口:Thread-1

    现在卖第9张 买卖票窗口:Thread-2

    现在卖第8张 买卖票窗口:Thread-2

    现在卖第7张 买卖票窗口:Thread-2

    现在卖第6张 买卖票窗口:Thread-2

    现在卖第5张 买卖票窗口:Thread-2

    现在卖第4张 买卖票窗口:Thread-2

    现在卖第3张 买卖票窗口:Thread-3

    现在卖第2张 买卖票窗口:Thread-3

    现在卖第1张 买卖票窗口:Thread-3

    窗口Thread-3票已经卖完

    窗口Thread-0票已经卖完

    窗口Thread-2票已经卖完

    窗口Thread-1票已经卖完

    有的卖的多有的卖的少。

    由此我产生了以下几个疑问:

    1,JAVA的线程是抢占式的,但又遵守支持时间片的操作系统的时间片调度,那么这里的抢占与时间片轮换之间又有怎样的关系,是怎么协调的?

    2,每个线程的时间片分配大小是否相等?

    3,以上程序中的线程为什么不是依次的执行,比如Thread-0执行后应该是Thread-1执行,但结果确实Thread-3在执行,当Thread-0睡眠过后,执行剩余的代码,外面等待的应该是Thread-2啊,那怎么会执行Thread-3呢?

    4,为什么每个线程的执行时间不是一样的长?

    期盼大家能帮下我--一个渴望学习JAVA的初学者

    展开

    展开全文
  • 线程状态(1)NEW(新建尚未运行/启动)还没调用start,或者调用了start()方法,不一定立即改变线程状态,中间可能需要一些步骤才完成一个线程启动。(2)RUNNABLE(处于可运行状态:正在运行或准备运行)start调用结束,...

    线程状态

    (1)NEW(新建尚未运行/启动)

    还没调用start,或者调用了start()方法,不一定立即改变线程状态,中间可能需要一些步骤才完成一个线程的启动。

    (2)RUNNABLE(处于可运行状态:正在运行或准备运行)

    start调用结束,线程由NEW变成RUNNABLE,存活着,并尝试占用CPU资源,yield操作时,线程还是Runnable状态,只是它有一个细节的内部变化,做一个简单的让步。在Java层面是Runnable的状态,并不代表一定处于运行中的状态,比如BIO中,线程正阻塞在网络等待的时候,看到的状态依然是Runnable状态,而底层线程已经被阻塞住了。

    (3)BLOCKED(等待获取锁时进入的状态)

    线程被挂起了,原因通常是因为它在等待一个锁,当某个synchronized正好有线程在使用时,一个线程尝试进入这个临界区,就会被阻塞,直到另一个线程走完临界区或发生了相应锁对象的wait操作后,它才有机会去争夺进入临界区的权利。当抢到锁之后,才会从blocked状态恢复到runnable状态。这个状态它好像什么也不做一样。

    (4)WAITING(通过wait方法进入的等待)

    当wait,join,park方法调用时,进入waiting状态。前提是这个线程已经拥有锁了。

    blocked和waiting状态的区别是:

    A、blocked是虚拟机认为程序还不能进入某个区域,因为同时进去就会有问题,这是一块临界区。

    B、发生wait等操作的先决条件是要进入临界区,也就是线程已经拿到锁了,自己可能进去做了一些事情,但此时通过判定业务上的参数,发现还有一些其他配合的资源没有准备充分,那么自己就等等再做其他事情。

    在waiting状态下,如果发生了interrupt操作,则处于该状态的线程在内部会抛出一个InterruptedException,这个异常应当在run方法内捕获,使得run方法正常地执行完成,当然捕获异常后,是决定让线程继续运行,还是结束等要根据业务场景才处理。

    如果发生了notify动作,则会从等待池当中唤醒一个线程重新恢复到Runnable状态,如果是notifyall操作,则唤醒所有等待线程。

    (5)TIMED_WAITING(通过sleep或wait timeout方法进入的限期等待的状态)

    通过wait(t),sleep(t),join(t),parkNanos,parkUntil等方法进入此状态。当时间达到时触发线程回到工作状态Runnable。

    interrupt只对处于waiting或timed_waiting状态的线程起作用,对其他状态不起作用。

    (6)TERMINATED(线程终止状态)

    线程结束了,就处于这种状态,也就是run方法运行完了。这只是Java语言级别的一种状态,在操作系统内部可能已经注销了相应的线程,或者将它复用给其他需要使用线程的请求。

    线程状态切换

    af2b944d171b09e2f8c70384ba182547.png

    详细图

    01e3abecc7782402f9c64b54bb7d518e.png

    线程状态源码

    /**

    * A thread state. A thread can be in one of the following states:

    *

    *

    {@link #NEW}

    * A thread that has not yet started is in this state.

    *

    *

    {@link #RUNNABLE}

    * A thread executing in the Java virtual machine is in this state.

    *

    *

    {@link #BLOCKED}

    * A thread that is blocked waiting for a monitor lock

    * is in this state.

    *

    *

    {@link #WAITING}

    * A thread that is waiting indefinitely for another thread to

    * perform a particular action is in this state.

    *

    *

    {@link #TIMED_WAITING}

    * A thread that is waiting for another thread to perform an action

    * for up to a specified waiting time is in this state.

    *

    *

    {@link #TERMINATED}

    * A thread that has exited is in this state.

    *

    *

    *

    *

    * A thread can be in only one state at a given point in time.

    * These states are virtual machine states which do not reflect

    * any operating system thread states.

    *

    * @since 1.5

    * @see #getState

    */

    public enum State {

    /**

    * Thread state for a thread which has not yet started.

    */

    NEW,

    /**

    * Thread state for a runnable thread. A thread in the runnable

    * state is executing in the Java virtual machine but it may

    * be waiting for other resources from the operating system

    * such as processor.

    */

    RUNNABLE,

    /**

    * Thread state for a thread blocked waiting for a monitor lock.

    * A thread in the blocked state is waiting for a monitor lock

    * to enter a synchronized block/method or

    * reenter a synchronized block/method after calling

    * {@link Object#wait() Object.wait}.

    */

    BLOCKED,

    /**

    * Thread state for a waiting thread.

    * A thread is in the waiting state due to calling one of the

    * following methods:

    *

    *

    {@link Object#wait() Object.wait} with no timeout

    *

    {@link #join() Thread.join} with no timeout

    *

    {@link LockSupport#park() LockSupport.park}

    *

    *

    *

    A thread in the waiting state is waiting for another thread to

    * perform a particular action.

    *

    * For example, a thread that has called Object.wait()

    * on an object is waiting for another thread to call

    * Object.notify() or Object.notifyAll() on

    * that object. A thread that has called Thread.join()

    * is waiting for a specified thread to terminate.

    */

    WAITING,

    /**

    * Thread state for a waiting thread with a specified waiting time.

    * A thread is in the timed waiting state due to calling one of

    * the following methods with a specified positive waiting time:

    *

    *

    {@link #sleep Thread.sleep}

    *

    {@link Object#wait(long) Object.wait} with timeout

    *

    {@link #join(long) Thread.join} with timeout

    *

    {@link LockSupport#parkNanos LockSupport.parkNanos}

    *

    {@link LockSupport#parkUntil LockSupport.parkUntil}

    *

    */

    TIMED_WAITING,

    /**

    * Thread state for a terminated thread.

    * The thread has completed execution.

    */

    TERMINATED;

    }

    展开全文
  • 专业版在前几个版本一直存在一个问题,就是在首页切换Tab的...我们需找到了原因其实是RxJava切换线程的问题,请求缓存从io线程切换回主线程需要等待一定的时间。看一段我们的测试代码。addSubscription(movieBoardUs...

    专业版在前几个版本一直存在一个问题,就是在首页切换Tab的时候每次都会转圈圈,我们已经使用了Retrofit缓存,正常来说读取缓存数据应该很快。转圈圈给我们的感觉是读取缓存很慢,我们开始怀疑Retrofit读取缓存的问题。我们需找到了原因其实是RxJava切换线程的问题,请求缓存从io线程切换回主线程需要等待一定的时间。看一段我们的测试代码。

    addSubscription(movieBoardUsecase.requestMainBoard(refresh)

    .subscribe(boardTop -> {

    time2 = (Formatter.getCurrentMillis() - time);

    Log.e("timeretrofit", "" + time2);

    }, throwable -> {

    }));

    time3 = Formatter.getCurrentMillis();

    addSubscription(movieBoardUsecase.requestMainBoard(refresh)

    .subscribeOn(Schedulers.io())

    .observeOn(AndroidSchedulers.mainThread())

    .subscribe(boardTop -> {

    Log.e("timeRXthread", "" + (Formatter.getCurrentMillis() - time3 - time2));

    getView().setData(boardTop);

    }, throwable -> {

    }));

    第一段我们不切换线程,直接在主线程请求缓存内的数据,打出发出请求再到获取到数据的时间。

    第二段我们正常的切换线程请求缓存,然后减去上面在主线程请求缓存的时间,就获取到切换线程所需要的时间。

    我们在页面状态由加载状态变成展示状态的时间。

    09-07 22:17:49.176 10745-10745/com.sankuai.moviepro E/timeretrofit: 4

    09-07 22:17:49.206 10745-10745/com.sankuai.moviepro E/timeRXthread: 26

    09-07 22:17:49.207 10745-10745/com.sankuai.moviepro E/status: 35

    上面是在模拟器上运行的时间,可能感觉时间很短,模拟器运行速度较快,参考价值不大,但已经能看出切换线程占用了大部分的耗时。我们换用真机,才能说明问题。

    09-08 10:24:42.539 26994-26994/com.sankuai.moviepro E/timeretrofit: 7

    09-08 10:24:42.639 26994-26994/com.sankuai.moviepro E/timeRXthread: 91

    09-08 10:24:42.644 26994-26994/com.sankuai.moviepro E/status: 112

    09-08 10:25:25.676 26994-26994/com.sankuai.moviepro E/timeretrofit: 13

    09-08 10:25:25.777 26994-26994/com.sankuai.moviepro E/timeRXthread: 88

    09-08 10:25:25.779 26994-26994/com.sankuai.moviepro E/status: 116

    09-08 10:25:51.392 26994-26994/com.sankuai.moviepro E/timeretrofit: 28

    09-08 10:25:51.609 26994-26994/com.sankuai.moviepro E/timeRXthread: 189

    09-08 10:25:51.611 26994-26994/com.sankuai.moviepro E/status: 247

    三组数据整体时间不是很稳定,但我们已经可以清楚地看出耗时的并不是Retrofit读取缓存的过程,大部分时间都消耗在RxJava切换线程上。

    既然我们已经找到了问题想想解决办法吧。我们可以直接想到的有两种方法,但行不行得通要去试试。

    1.在请求之前判断是否存在Http缓存。

    2.自己增加一层缓存,优先使用内存缓存,避开retrofit发请求。

    第一种方法,我们要在发请求之前知道是否存在Http缓存,http缓存的位置是我们自己指定的,专业版的缓存目录是在应用目录下的cache/responses,下面有好多文件,文件名都是经过加密的,都是.0和.1的文件还有一个journal文件,关于这些文件查了一些资料,okhttp缓存浅析

    .0的文件里面是header

    .1文件里面是返回的具体内容,即json数据

    journal文件里面保存的是每一条reponse记录状态。包括读取,删除,写入等动作。

    文件名的加密方式是MD5,可以参考okHttp的Cache。

    public static FilterInputStream getFromCache(String url) throws Exception {

    File cacheDirectory = CacheUtils.getCacheDir(MovieProApplication.getContext(), "responses");

    DiskLruCache cache = DiskLruCache.create(FileSystem.SYSTEM, cacheDirectory,

    201105, 2, 10 * 1024 * 1024);

    cache.flush();

    String key = Util.md5Hex(url);

    final DiskLruCache.Snapshot snapshot;

    try {

    snapshot = cache.get(key);

    if (snapshot == null) {

    return null;

    }

    } catch (IOException e) {

    return null;

    }

    okio.Source source = snapshot.getSource(1) ;

    BufferedSource metadata = Okio.buffer(source);

    FilterInputStream bodyIn = new FilterInputStream(metadata.inputStream()) {

    @Override

    public void close() throws IOException {

    snapshot.close();

    super.close();

    }

    };

    return bodyIn ;

    }

    但是弄了半天我们有一个关键的问题,就是匹配缓存使用的是URL,但是我们在Presenter或者Fragment中并不能获取到URL,要修改的话,改动将会很大,所以这一种方法失败。

    第二种是我们自己写内存缓存,还是存在问题,我们要把页面所有的数据缓存起来,使用一个Map,问题就是用什么作为获取缓存的匹配原则呢,正常也应该是通过URL,但是URL的方式行不通,我们只能拿到的是Observable,也无从匹配啊。后来我们重新思考了一下问题,我们当初是为了解决转圈圈的问问题,转圈圈的问题是从loaddata开始,在setData的是后结束。我们只需要避开这个过程,也就不会出现转圈圈的问题,但这只是一个比较差的解法,我们只缓存setData的数据,如果loaddata的时候数据不为空我们直接调用setData,但这样,如果页面有其他数据的话我们setData直接使用缓存,页面展示出来,但其他的请求数据还没有获取到,这样展示出来也会有问题,对于其他的请求我们只能自己写缓存,这样确实不是一个好的解决方法,更好的解决方法还在寻找。

    展开全文
  • Java线程状态及切换一、什么是Java线程状态在Java程序中,用于描述Java线程六种状态:新建(NEW):当前线程,刚刚新建出来,尚未启动。运行(RUNNABLE):当前线程,处于竞争CPU时间分片或已经获得CPU时间状态。...

    Java线程状态及切换

    一、什么是Java线程状态

    在Java程序中,用于描述Java线程的六种状态:

    新建(NEW):当前线程,刚刚新建出来,尚未启动。

    运行(RUNNABLE):当前线程,处于竞争CPU时间分片或已经获得CPU时间片的状态。

    等待(WAITTING):当前线程,处于休眠,不参与CPU时间片竞争的状态。

    定时等待(TIMED_WAITTING):当前线程,处于定时休眠,暂时不参与CPU时间片竞争的状态。

    阻塞(BLOCKED):当前线程,处于阻塞,不参与CPU时间片竞争的状态。

    终止(TERMINATED):当前线程,处于最终停止的状态。

    新建状态,只能进入运行状态。而终止状态无法再转为其他状态。

    等待/定时等待与阻塞,差别就是后者需要一个事件信号(如其他线程放弃当前线程需要的排他锁),才可以进行状态切换。当然,强行关闭也是可以的。

    Java线程的实现并不受JVM规范约束,故不同虚拟机的实现,往往不同。目前主流的HotSpot是将每个Java线程直接映射到一个操作系统的原生线程,从而由操作系统完成一系列的线程调度

    二、哪里看Java线程状态

    查看Java线程状态,主要存在三种方式:

    java.lang.Thread.State下可以直接看到Java的六种线程状态

    Java运行时,程序内部可以通过Thread.getState()获取目标线程状态

    Java运行时,程序外部可以通过jstack等工具,查看线程状态

    有关jstack等工具等使用,后续会有博客,专门阐述。

    三、什么时候变换Java线程状态

    Java线程状态的切换嘛。不啰嗦,直接上图。

    dcfab5f39579f0db7c1873330229e2e6.png

    这张图涵盖了Java线程状态切换的各类方法。相较网上一些图片,更为详尽一些。

    如果有所遗漏,可以告诉我,我会及时填补上。

    四、谁在使用Java线程状态

    日常开发中,我们并不会直接与线程状态进行交互。

    我们往往直接使用JDK包装好的工具,如JUC包下的各类工具等。

    举个栗子

    线程池中的应用

    位置:com.sun.corba.se.impl.orbutil.threadpool.ThreadPoolImpl#close

    // Note that this method should not return until AFTER all threads have died.

    public void close() throws IOException {

    // Copy to avoid concurrent modification problems.

    List copy = null;

    synchronized (workersLock) {

    copy = new ArrayList<>(workers);

    }

    for (WorkerThread wt : copy) {

    wt.close();

    while (wt.getState() != Thread.State.TERMINATED) {

    try {

    wt.join();

    } catch (InterruptedException exc) {

    wrapper.interruptedJoinCallWhileClosingThreadPool(exc, wt, this);

    }

    }

    }

    threadGroup = null;

    }

    实际查看JDK后发现,JDK中其实也没有辣么多的实例,并且大多数直接关联线程状态的,也是一些状态查看的东东。

    这在文章开头就说,Java线程操作,是很底层的,甚至其实现都不包含在虚拟机规范中。

    主流的HotSpot,也是直接将Java线程映射到系统线程,由系统进行一系列的线程调度处理。

    所以,在JDK中,是直接对线程状态进行处理的部分是很少的。

    五、为什么需要线程状态

    1.为什么需要线程状态这一概念

    这个问题,可以从两个角度来说明:生命周期与资源管理

    一方面,线程状态很好地刻画了线程的整个生命周期,对生命周期中不同阶段进行了有效划分。

    另一方面,资源是有限的,需求是无限的。所以需要将系统资源有意识地进行调度,合理利用比较优势,追求帕累托最优。

    实现后者的,就是利用线程在生命周期的不同阶段这一天然属性带来的状态刻画,进行的分组。CPU调度只需要关注运行状态的线程。而阻塞,等待等线程,都有着属于自己的一套处理方式。最终获得资源(开发时对复杂性的应对,运行时对系统资源对消耗,应用者心智模型的成长等)的优化分配。

    2.JDK中为什么需要定义Java线程状态

    前文有说到,Java中很少直接使用到线程状态。那么为什么还要在JDK中定义Java的六种线程状态呢?

    一方面,通过信息透明的方式,降低使用者使用时建立心智模型的成本。如,现在的我们可以通过打印日志,打断点,快速了解Java的各个线程状态,并清楚了解产生的原因。从而大大提高了我们对Java线程的认识,进而更为愉快地拥抱JUC包下诸如线程池等工具。

    另一方面,通过可以直接应用的状态枚举,我们可以很好地对现有工具进行二次开发等。如我们可以通过扩展AQS,并在其中添加线程状态的校验,从而得到定制化的线程同步工具。

    六、如何使用线程状态

    使用的方式,我已经在上文说了:学习Java线程,定制线程相关工具开发。

    这里给出一个有关线程学习的demo:

    /**

    * @program: learning

    * @description: 用于确认线程状态问题

    * @author: Jarry

    * @create: 2020-10-26 22:25

    **/

    public class ThreadState {

    public static void main(String[] args) {

    threadStateTest();

    // threadStateTest2();

    // threadStateWithBlocked();

    // threadStateWithException();

    // threadStateWithSuspend();

    }

    /**

    * 实践证明:Thread.suspend()与Thread.resume()不会改变线程状态

    * 线程状态该是Waiting,就Waiting。该Timed_Waiting就Timed_Waiting

    * Thread.suspend()与Thread.resume()只是挂起目标线程(并且不会释放锁资源)

    */

    private static void threadStateWithSuspend() {

    Thread thread1 = new Thread(() -> {

    // LockSupport.park();

    LockSupport.parkNanos(2000000000);

    });

    thread1.start();

    printThreadState(thread1);

    LockSupport.parkNanos(500000000);

    printThreadState(thread1);

    thread1.suspend();

    printThreadState(thread1);

    LockSupport.parkNanos(500000000);

    printThreadState(thread1);

    thread1.resume();

    LockSupport.parkNanos(500000000);

    printThreadState(thread1);

    // LockSupport.unpark(thread1);

    }

    /**

    * 展现线程阻塞状态

    */

    private static void threadStateWithBlocked() {

    Runnable runnable = new Runnable() {

    @Override

    public void run() {

    synchronized (ThreadState.class) {

    // LockSupport.parkNanos(2000000000);

    LockSupport.park();

    }

    }

    };

    Thread thread1 = new Thread(runnable);

    Thread thread2 = new Thread(runnable);

    thread1.start();

    LockSupport.parkNanos(500000000);

    thread2.start();

    // 加上以下时间间隔,则结果:Runnable->Blocked

    // 推论:Thread.start()会将线程状态设置为Runnable,然后在遇到sync的锁,再切换为Blocked状态

    // LockSupport.parkNanos(500000000);

    printThreadState(thread2);

    LockSupport.parkNanos(500000000);

    printThreadState(thread2);

    LockSupport.parkNanos(500000000);

    LockSupport.unpark(thread1);

    LockSupport.unpark(thread2);

    }

    /**

    * 由于底层实现机制的不同(相较于其他waiting的方法),无法直接进行Object.wait(),否则会抛出以下异常

    * @exception java.lang.IllegalMonitorStateException

    * object.wait()进行wait的方法,是直接对其wait_set进行操作

    */

    private static void threadStateWithException() {

    Thread thread1 = new Thread(() -> {

    try {

    ThreadState.class.wait(2000);

    } catch (InterruptedException e) {

    e.printStackTrace();

    }

    });

    thread1.start();

    LockSupport.parkNanos(1000000000);

    printThreadState(thread1);

    }

    /**

    * Object.wait()的使用

    */

    private static void threadStateTest3() {

    Thread thread1 = new Thread(() -> {

    synchronized (ThreadState.class) {

    try {

    ThreadState.class.wait(2000);

    } catch (InterruptedException e) {

    e.printStackTrace();

    }

    }

    });

    thread1.start();

    LockSupport.parkNanos(1000000000);

    printThreadState(thread1);

    }

    /**

    * 确定LockSupport.parkNacos()是否可以生成Time_Waiting状态

    */

    private static void threadStateTest2() {

    Thread thread1 = new Thread(() -> {

    LockSupport.parkNanos(2000000000);

    });

    thread1.start();

    printThreadState(thread1);

    LockSupport.parkNanos(1000000000);

    printThreadState(thread1);

    }

    /**

    * 查看到除Blocked以外的所有线程状态

    */

    private static void threadStateTest() {

    Thread thread1 = new Thread(() -> {

    synchronized (ThreadState.class) {

    // Runnable

    printThreadState(Thread.currentThread());

    // 1.Thread.sleep(time)

    try {

    Thread.sleep(2000);

    } catch (InterruptedException e) {

    e.printStackTrace();

    }

    // 2.Object.wait(time)

    // try {

    // ThreadState.class.wait(2000);

    // } catch (InterruptedException e) {

    // e.printStackTrace();

    // }

    // 3.Thread.join(time)

    // try {

    // Thread.currentThread().join(2000);

    // } catch (InterruptedException e) {

    // e.printStackTrace();

    // }

    // 4.LockSupport.parkNanos(time);

    // LockSupport.parkNanos(2000000000);

    // 5.LockSupport.parkUntil(timeStamp);

    // LockSupport.parkUntil(System.currentTimeMillis()+2000);

    LockSupport.park();

    }

    });

    thread1.setName("test_thread");

    // New

    printThreadState(thread1);

    thread1.start();

    LockSupport.parkNanos(1000000000);

    // Timed_waiting

    printThreadState(thread1);

    LockSupport.parkNanos(2000000000);

    // Waiting

    printThreadState(thread1);

    LockSupport.unpark(thread1);

    LockSupport.parkNanos(1000000000);

    // Terminated

    printThreadState(thread1);

    }

    private static void printThreadState(Thread thread) {

    System.out.println("current Thread(" + thread.getName()+":" + thread.getId() + ") state:" + thread.getState());

    }

    }

    代码中有一些细碎的知识点,就不在这里赘述了。感兴趣的小伙伴,可以自己看看注释,自行验证。

    七、扩展:系统状态(三态&五态)

    操作系统就包含进程管理,作业管理,文件管理等。其中进程管理,就涉及系统状态的三态模型与五态模型。

    其中,三态模型包含以下三种状态:

    就绪状态

    运行状态

    阻塞状态

    而五态模型则包含以下五种状态:

    运行状态

    静止就绪态

    活跃就绪态

    静止阻塞态

    活跃阻塞态

    具体状态切换等,可以看我之前写的一篇博客:

    系统架构设计师-操作系统

    最后,愿与诸君共进步。

    八、附录

    补充:WAITTING/TIMED_WAITTING与BLOCKED的区别

    其实,我之前也挺纠结这个问题的。

    当时的想法是WAITTING/TIMED_WAITTING是由JVM自己维持,而BLOCKED是由系统维持的。后面看到主流的HotSpot是将线程映射到系统原生线程的,所以这个想法大概率是错误的。

    那么两者区别是什么呢?

    直到我在上文的示例代码中,BLOCKED状态的线程,在其他线程释放其所需的锁时,该线程是先转为RUNNING状态,再变为其他状态。这引起我的注意。

    最后在stackOverFlow的一篇文章(Difference between WAIT and BLOCKED thread states)中,看到这样的解释:

    The important difference between the blocked and wait states is the impact on the scheduler. A thread in a blocked state is contending for a lock; that thread still counts as something the scheduler needs to service, possibly getting factored into the scheduler's decisions about how much time to give running threads (so that it can give the threads blocking on the lock a chance).

    Once a thread is in the wait state the stress it puts on the system is minimized, and the scheduler doesn't have to worry about it. It goes dormant until it receives a notification. Except for the fact that it keeps an OS thread occupied it is entirely out of play.

    This is why using notifyAll is less than ideal, it causes a bunch of threads that were previously happily dormant putting no load on the system to get woken up, where most of them will block until they can acquire the lock, find the condition they are waiting for is not true, and go back to waiting. It would be preferable to notify only those threads that have a chance of making progress.

    (Using ReentrantLock instead of intrinsic locks allows you to have multiple conditions for one lock, so that you can make sure the notified thread is one that's waiting on a particular condition, avoiding the lost-notification bug in the case of a thread getting notified for something it can't act on.)

    简单说,就是CPU时间片不会考虑WAITTING/TIMED_WAITTING状态。

    但是,虽然BLOCKED状态的线程无法获得CPU时间片,但是系统调度时,依旧会考虑BLOCKED状态的线程,将其置于调度计算中。

    如果哪位小伙伴对这方面有了解,希望可以聊一聊。

    参考

    展开全文
  • 对于上下文切换不同的操作系统模式也不尽...时间片是CPU分配给各个线程的时间,因为时间片非常短,所以CPU通过不停地切换线程执行,让我们感觉多个线程是同时执行的,时间片一般是几十毫秒(ms)CPU通过时间片分配算...
  • Java线程状态及切换一、什么是Java线程状态在Java程序中,用于描述Java线程六种状态:新建(NEW):当前线程,刚刚新建出来,尚未启动。运行(RUNNABLE):当前线程,处于竞争CPU时间分片或已经获得CPU时间状态。...
  • 目标:Number线程类执行数字递增并输出,并且没增加两个就切换到另外一个线程,Letter线程类执行字母递增并输出,并且没输出一个就切换到另外一个线程。主类:public static void main(String[] args) {Print ...
  • 前言:今天被一个同学问到一个很有意思题目,在这个看起来很简单程序中却涉及了Java变量可见性和线程之间时间切换的知识,感觉很典型,所以写这篇文章总结一下。帮助文档连接:...
  • 只有被 CPU 调度之后,线程才开始执行,当 CPU 分配给的时间片到了,又回到就绪状态,继续排队等候。二、线程控制的基本方法isAlive():判断线程是否还活着。start 之后,终止之前都是活的。getPriority():获得线程...
  • 线程的上下文切换,多线程频繁上下文切换利用时间片轮转的方式,CPU给每个任务都服务一定的时间,然后把当前任务的状态保存下来,在加载下一个任务后,继续服务下一个任务,这个过程叫做上下文切换。时间片轮转的...
  • 关于Java中时区切换

    2017-02-17 11:24:12
    最近困扰于Java的时区切换。 想要创建默认时区为GMT+1的, 6.30的时间; 原代码: SimpleDateFormat format_HHmm = new SimpleDateFormat(DATE_FORMAT_TYPE_HHmm); String timezone = "GMT+1"; Calendar ...
  • 线程状态线程可以有6种状态:New(新建)Runnable(可运行)Blocked(被阻塞)Waiting(等待)Timed waiting(计时等待)Terminated(被终止)New:new Thread()后线程状态就是新建。Runnable:线程一旦调用start()方法,无论...
  • 对于上下文切换不同的操作系统模式也不尽...时间片是CPU分配给各个线程的时间,因为时间片非常短,所以CPU通过不停地切换线程执行,让我们感觉多个线程是同时执行的,时间片一般是几十毫秒(ms)CPU通过时间片分配算...
  • Java语言定义了5种进程状态,在任意一个时间点中,一个进程只能有且只有其中一种状态。 新建(NEW) 使用new Thread或者实现了Runnable接口创建thread对象,这个对象状态是new,也可以说是初始化状态,并没有...
  • 1.新建(NEW):新创建了一个线程对象。2.可运行(RUNNABLE):线程对象创建后,其他线程...3.运行(RUNNING):可运行状态(runnable)线程获得了cpu 时间片(timeslice) ,执行程序代码。4.阻塞(BLOCKED):阻塞状态是指...
  • CPU通过给每个线程分配CPU时间片来让线程执行代码,时间片是CPU分配给线程执行的时间,CPU通过不停的切换线程,并给线程时间片让它执行指令,这个时间片非常非常的短,一般是几十毫秒,让我们感觉多个线程在同时执行. ...
  • 【注】:只有被 CPU 调度之后,线程才开始执行, 当 CPU 分配给你的时间片到了, 又回到就绪状态, 继续排队等候.线程控制的基本方法:isAlive():判断线程是否还活着,start之后,终止之前都是活的;getPriority():获得...
  • Java线程状态切换

    2020-08-09 13:07:46
    首先我们还是以一个牛客网上错题例子...3.运行(running):可运行状态(runnable)线程获得了cpu时间片(timeslice),执行程序代码。 4.阻塞(block):阻塞状态是指线程因为某种原因放弃了cpu使用权,也即让出了cp
  • 先要掌握三个重要概念1、上下文切换每个CPU在同一时间只能执行一个线程,Linux采用是抢占式调度,即为每个线程分配一定执行时间,当到达执行时间、线程中有IO阻塞或高级优先线程要执行时,Linux将切换执行线程...
  • 1. 上下文切换的概念CPU通过时间片分配算法来循环执行任务,当前任务执行一个时间片后会切换到下一个任务。在切换前会保存上一个任务的状态...时间片是CPU分配给各个线程的时间,因为时间片非常短,所以CPU通过不停...
  • 上下文切换CPU通过时间片分配算法来循环执行任务,当前任务执行一个时间片后会切换到下一个任务。但是在切换前会保存上一个任务状态,以便下次切换回这个任务时,可以再加载这个任务状态。所以任务从保存到再...
  • Java的时间操作,也许大家都很熟悉,Date、Calendar、SimpleDateFormat等。但或许我们都只是会调用常见接口方法。今天解决的bug,关于TimeZone,即时区。 经常有人发现时间不对,比如相差8个小时等等,其真实原因...
  • ava中线程生命周期大体可分为5种状态。1. 新建(NEW):新创建了一个线程对象。2. 可运行(RUNNABLE):线程对象创建后...3. 运行(RUNNING):可运行状态(runnable)线程获得了cpu 时间片(timeslice) ,执行程序代码...
  • Java线程状态切换详解

    2018-09-18 19:17:37
    一、线程状态说明 java.lang.Thread类中定义了线程状态枚举java.lang.Thread.State,以下为各状态说明。 1、NEW(新建) NEW是线程调用new()创建后且...就绪状态线程在系统调度分配时间片后进入运行中。 Thre...
  • Java语言中定义了5种线程状态,在任意一个时间点,一个线程只能有且只有其中一种状态,这5种状态是: 新建(New):创建后尚未启动线程处于这种状态。 运行(Runable):包括了操作系统线程状态中Running和...
  • java线程状态切换

    2018-05-17 11:01:06
    新创建一个新线程对象后,再调用他start()方法,...Runnable状态和Running状态可相互切换,因为有可能线程运行一段时间后,有其他高优先级线程抢占了CPU资源,这时此线程就从Running状态变成Runnable状态。 ...
  • Java线程状态及切换一、什么是Java线程状态在Java程序中,用于描述Java线程六种状态:新建(NEW):当前线程,刚刚新建出来,尚未启动。运行(RUNNABLE):当前线程,处于竞争CPU时间分片或已经获得CPU时间状态。...
  • Java线程状态及切换

    2020-11-11 09:43:36
    Java线程状态及切换 一、什么是Java线程状态 在Java程序中,用于描述Java线程六种状态: 新建(NEW):当前线程,刚刚新建出来,尚未启动。 运行(RUNNABLE):当前线程,处于竞争CPU时间分片或已经获得CPU时间片...
  • 虽然并不是真正意义上的“同一时间点”,而是 多个任务或进程共享一个CPU,并交由操作系统来完成多任务间对CPU的运行切换,以使得每个任务都有机会获得一定的时间片运行。再后来发展到多线程技术,使得在一个程序...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 3,771
精华内容 1,508
关键字:

java的时间切换

java 订阅