Java并发编程 - 逐级深入 看线程的中断

Java线程中断攻略: 详解Java线程中断及线程中断的几种使用场景 在多线程编程中,线程中断技术是确保程序健壮性和可靠性的不可或缺的一部分。本文将深入探讨Java中的线程中断技术,以通俗易懂的方式介绍其概念、机制以及在实际项目中的应用。 阅读详情

最近有足够的空闲时间 去东看看西看看,突然留意到在Java的并发编程中,有关线程中断的,以前初学时一直没弄清楚的一些小东西。
于是,刚好把收获简单的总结一下,通过此文来总结记录下来。

从源码看线程的状态

在开始分析线程的中断工作之前,我们肯定要先留意一个点,那就是肯定是有开启,才会有与之对应的中断工作出现。
开启一个线程的工作,相信每个Javaer都烂熟于心。它很简单,new一个thread对象,然后调用start方法开启线程。
那么,一个好玩的问题就出现了:既然开启一个线程的步骤如此简单明了,那么中断又能有什么值得说的呢?
是的,假设我们第一次接触到Thread类,我们已经发现start用于开启一个线程。那么通过查找该类的方法接口,我们一定会发现与之对应的stop()方法。
但事实上是该方法已经明确的被指定为过时了,即不赞成使用。具体原因我们可以参照API说明文档。但也正是因为这样:
即如此“显眼”的一个中断线程的方法被明确的声明为不赞成使用,所以我们才有必要专门去看看,中断一个线程,有哪些值得学习的东西。

但在了解中断线程的工作之前,我们肯定要先对线程这个东西本身的状态有一个了解才行。这个道理很简单:
我们脑子里一定有类似的电影场景:两个人发生冲突,一个人情绪失控之下,抓起手边的一个东西就砸在另一个人头上,另一个人“吧唧 ”,倒地不起。
在这里,我们为什么举这样一个狗血的场景呢?因为电影里接下来的剧情多半就是,这个大兄弟认为自己杀人了,仓皇失措,接着怎样怎样…..
这就联系上我们之前说的“状态”,出现这样的剧情正是因为分不清状态:当发现人流血倒地,下意识就会认为光荣了;但别人也有可能只是昏迷而已。
这对应到我们的并发编程来说也是一个道理:假设我们当前查看的时候,发现某个线程的工作内容已经没有执行了,那是不是线程就已经中断了呢?
答案当然是不一定。所以说,在了解如何中断一个线程之前,我们自然要先清楚线程的各种状态,才知道究竟要符合什么情况,才代表线程彻底中断。

通常一些资料或者大部分的书中,对于线程的状态都有类似如下的一个划分:

  • new - 创建状态:顾明思议,Java通过new创建了一个线程对象过后,该线程就处于该状态。
  • runnable- 可执行状态:也就是指在线程对象调用start()方法后进入的状态。但需要注意的是该状态是“可执行状态”而不是“执行状态”。也就是说,当一个线程对象调用start方法后,只是意味着它获取到了CPU的执行资格,并不代表马上就会被运行(CPU此时当然可能恰好切换在其它线程上做处理),只有具备了CPU当前执行权的线程才会被执行。
  • non Runnable- 不可执行/阻塞状态:也就是通过一些方法的控制,使该线程暂时释放掉了CPU的执行资格的状态。但此时该线程仍然是存在于内存中的。
  • done -退出状态:简单的说也就是当线程进入到退出状态,就意味着它消亡了,不存在了。

这种划分没有错,但这里我们不依照这个划分。而是通过Thread类的源码,来一探究竟。
如果我们查看Thread类的方法接口列表,我们会发现有一个方法很“扎眼”,即“getState”。
没错,我们发现对于该方法的描述正是:“返回线程的状态”。该方法的返回类型是State。
这是定义于Thread内部的一个枚举类型,这就好办了,我们看看该枚举的定义究竟是怎么样的:

 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:
         * <ul>
         *   <li>{@link Object#wait() Object.wait} with no timeout</li>
         *   <li>{@link #join() Thread.join} with no timeout</li>
         *   <li>{@link LockSupport#park() LockSupport.park}</li>
         * </ul>
         * 
         * <p>A thread in the waiting state is waiting for another thread to
         * perform a particular action.  
         *
         * For example, a thread that has called <tt>Object.wait()</tt>
         * on an object is waiting for another thread to call 
         * <tt>Object.notify()</tt> or <tt>Object.notifyAll()</tt> on 
         * that object. A thread that has called <tt>Thread.join()</tt> 
         * 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:
         * <ul>
         *   <li>{@link #sleep Thread.sleep}</li>
         *   <li>{@link Object#wait(long) Object.wait} with timeout</li>
         *   <li>{@link #join(long) Thread.join} with timeout</li>
         *   <li>{@link LockSupport#parkNanos LockSupport.parkNanos}</li> 
         *   <li>{@link LockSupport#parkUntil LockSupport.parkUntil}</li>
         * </ul>
         */
        TIMED_WAITING,

        /**
         * Thread state for a terminated thread.
         * The thread has completed execution.
         */
        TERMINATED;
    }

通过源码我们发现,Java为线程定义了6种状态,从而构成了Thread的整个生命周期。6种状态分别是:NEW、RUNNABLE、BLOCKED、WAITING、TIMED_WAITING、TERMINATED。

在这里我们只分别的简要概括一下这六种状态代表什么,如果想要具体的了解这些状态,可以查看源码和注释或者查阅API说明文档。

  • NEW - 至今尚未启动的线程的状态。
    (该状态最好理解,就是一个Thread对象创建(new)出来之后,就进入这种状态。)
  • RUNNABLE - 可运行线程的线程状态。
    (有很多种方式进入该状态,如调用start,或者wait,sleep达到超时时间,亦或者wait后被notify等等)
  • WAITING - 某一等待线程的线程状态。
    (调用wait,join,LockSupport.park等方法就会进入该状态)
  • TIMED_WAITING - 具有指定等待时间的某一等待线程的线程状态。
    (与WAITING状态不同的就是,该状态具有等待超时。例如调用Thread.sleep以及带有超时值得wait、join等方法就会进入该状态)
  • BLOCKED - 受阻塞并且正在等待监视器锁的某一线程的线程状态
    (很明显,与等待线程状态不同之处就在于,该状态还要等待同步锁)
  • TERMINATED - 已终止线程的线程状态。线程已经结束执行。

现在我们就对一个Thread整个生命周期内的各种可能出现的状态有了一个了解。接下来我们就来看如何让一个线程进入中断(TERMINATED )。

一步一步看各种线程中断

正常自然消亡

虽然我们在之前打下了不错的基础,但很明显,我们还需要一个切入点。幸运的是,我们注意到一点信息:
对于TERMINATED的状态的描述是这样的:已终止线程的线程状态。线程已经结束执行。那么,重点就在于线程已经结束执行。
由此我们推测,何为线程结束执行?是不是线程任务的内容已经执行完毕呢?我们可以通过尝试通过写一段代码来验证一下:

import java.lang.Thread.State;

public class Demo {

    private static Thread sThread;

    public static void main(String[] args) {
        sThread = new Thread(new Runnable() {

            @Override
            public void run() {
                System.out.println("2==>" + sThread.getState());
            }
        });
        System.out.println("1==>" + sThread.getState());
        sThread.start();

        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("3==>" + sThread.getState());
    }
}

这段代码最终运行完成后,输入到控制台的信息如下:

1==>NEW
2==>RUNNABLE
3==>TERMINATED

通过输出信息我们验证了:

1、当我们new出一个Thread对象,该对象就进入了NEW状态。
2、当调用start方法之后,线程就进入了RUNNABLE状态。
3、当线程的工作任务,即run()方法中的内容执行完毕,线程就进入了TERMINATED状态。

也许有刚开始接触Java的朋友会好奇在调用sThread.start之后,为什么通过sleep让线程休眠了2秒。
这其实也是值得一说的,那就是一定要明白RUNNABLE只是代表可执行,而并非立马执行。
简单的说,也就是RUNNABLE状态下的线程仅仅是具备执行资格而已,到底轮不轮到它执行,还得看CPU大哥翻不翻你的牌子。
所以,我们也可以记住这样一点:即使当前对线程调用了start方法,也不要以为就会即刻开始该线程run()方法的执行。

不信我们可以试着将让线程sleep的代码删除,然后再次运行程序,会发现输出结果多半会变为:

1==>NEW
3==>RUNNABLE
2==>RUNNABLE

道理很简单,调用了sThread.start,该线程就进入了RUNNABLE状态。可惜的是CPU没有翻它的牌子,而是选择了继续执行“main thread”的内容。
于是我们看见先打印了标记为”3==>”的内容,这个时候主线程的内容执行完了,Cpu切换,才执行mThread,从而输出”2==>…”

通过标记控制中断

到了这个时候,我们发现,有个毛的趣啊?线程中断不是也很容易吗?让它执行完工作任务不就搞定了吗?
这样说没错,但基本上很多时候我们很明显不可能只在一个线程内执行如此简单的工作,而是会存在循环。
这个时候如何控制线程中断?没错实际上也很简单,就像如何退出一个普通的循环一样,我们也可以通过循环标记来中断一个线程。

我们来看如下的一段测试代码:

public class Demo {

    private static Thread sThread;
    private static boolean KEEP_RUNNING = true;
    private static int position;

    public static void main(String[] args) {
        sThread = new Thread(new Runnable() {

            @Override
            public void run() {
                while (KEEP_RUNNING) {
                    try {
                        if (++position < 5) {
                            Thread.sleep(2000);
                        } else {
                            KEEP_RUNNING = false;
                        }
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        });
        sThread.start();

        while (sThread.getState() != State.TERMINATED) {
            System.out.println("sThead's state is ==>" + sThread.getState());
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }

        System.out.println(sThread.getState());
    }
}

运行该段代码的输出结果如下:

sThead’s state is ==>TIMED_WAITING
sThead’s state is ==>TIMED_WAITING
sThead’s state is ==>TIMED_WAITING
sThead’s state is ==>TIMED_WAITING
TERMINATED

我们来分析一下发生了什么:首先,sThread的run()方法中是一个while循环,控制循环的标记是一个布尔型的变量KEEP_RUNNING。
然后,我们每一次循环我们都会对一个int型的变量position进行自增并且判断,当小于5,我们就会让线程休眠2秒。否则就修改循环标记。
与此同时,我们在主线程当中也定义了一个while循环,判断的条件是只要sThread的状态不为TERMINATED,就在循环内输出sThread的状态。

我们需要明白这段程序运行的过程究竟是怎么样的,简单来说就是:
在postion小于5的时候,因为在main thread与sThead中都有调用sleep方法,所以cpu资格会来回切换。
也就是说,main thread和sThead会来回执行,每次position自增运算一次然后休眠,随之主线程输出一次sThead的状态。
由此我们同时验证了另外一点,就是调用带有超时参数的sleep方法,线程则会进入TIMED_WAITING状态。
当position自增运算到不再小于5,KEEP_RUNNING标记将被修改为false,这时sThread内的循环就将结束。
这其实也就意味着sThread的线程任务执行完毕,于是线程就完成了中断。

循环标记并非万能,interrupt来帮忙

到目前为止,我们已经掌握了一些让线程中断的操作。通常来说,它们足够使用了。但是,正如你所见,这仅仅指通常来说。
而编程的工作就是这么操蛋,往往就有很多不通常的情况出现。那么,我们接着来看这样一段代码:

public class Demo {

    private static Thread sThread;
    private static boolean KEEP_RUNNING = true;

    public static void main(String[] args) {
        sThread = new Thread(new Runnable() {

            @Override
            public void run() {
                while (KEEP_RUNNING) {
                    try {
                        Thread.sleep(2000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    for (int i = 1; i <= 5; i++) {
                        System.out.println(i + "==>"
                                + "the thread is running...");
                    }

                }
            }
        });
        sThread.start();

        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        stopThread();

    }

    private static void stopThread() {
        System.out.println("we gonna stop sThread...");
        KEEP_RUNNING = false;
    }
}

输出结果如下:

we gonna stop sThread…
1==>the thread is running…
2==>the thread is running…
3==>the thread is running…
4==>the thread is running…
5==>the thread is running…

我们先不去分析这个结果出现的原因,至少从这个输出结果我们发现一件事情,那就是:
虽然我们已经在外部将循环标记KEEP_RUNNING设置为false了,却发现sThread在之后并未被中断,仍然执行了一次任务。

这个结果出现的原因实际上也不是那么难理解,说到底任然是cpu执行权切换造成的。
当sThread执行了start(),接着主线程首先sleep 2s。于是sThread开始执行,这时判断标记为true,进入循环,此时sThread则会sleep,修眠2秒。
那么这个时候cpu便切换到了主线程运行,于是stopThread()方法得以执行,输出对应信息,然后设置KEEP_RUNNING为false。
理想状态下,这个时候sThread就应该中断了才对。但遗憾的是恢复之后线程并不是从头开始循环判断,而是接着sThread休眠之前的位置开始执行。
那么就造成了sThread恢复之后,会跳过while循环,接着上次sleep的代码之后执行,于是for循环开始,输出对应信息。

于是我们发现了:如果想要操作的线程当前处于阻塞(冻结)的状态,那么通过标记的方式并不能够确保一定能让指定线程立刻中断。
所以很显然,我们需要另外一种方式来确保线程的中断了。这个时候如果去网上查资料或者自己查看方法列表,
多半就有这样一个方法出现在你的眼前,那就是”interrupt“,对于interrupt方法,API文档的说明是”中断线程“。

这个时候,似乎一切就变得很容易了。但实际上通过使用,你会发现并没有那么容易。
而更坑爹的是,网上大部分的资料对于该方法的使用说明,都是复制粘贴API文档中的内容。这就让我们这些菜鸟在初学的时候完全摸不着头脑。

我们看到这个方法的命名,会很容易有一种错觉,那就是:如果我们想在某个时候中断一个线程的执行,那么就在外部调用这个方法。
看上去十分的有理有据,但我们要做的,自然就是通过代码来验证一下是否真的行得通:

    public static void main(String[] args) {
        sThread = new Thread(new Runnable() {

            @Override
            public void run() {
                while(true){
                    System.out.println("the thread is running");
                    sThread.interrupt();
                }
            }
        });
        mThread.start();

    }

在以上代码中,按照我们的推断来说,程序应该在输出一次”the thread is running”后,则被中断。
但实际的情况,这并没有卵用,我们会发现程序仍然将无限的输出该信息。这是怎么回事呢?

那么,我们究竟应该怎么来使用interrupt方法呢?实际上我们只需要明白一个原理:
那就是该方法虽然名为“中断”,但实际上它做的工作并不是真的中断线程,而是去设置一种“中断状态”。
所以说,与其说interrupt是去中断线程,不如说它是在设置一个标识,告诉线程当前应该或者说可以被中断了。
这个时候我们发现,如果是这样说来的话,那么这与我们之前说的循环标记似乎没什么区别啊?
确实是这样的,因为通常我们都可以这样类似下面这样去使用它:

            sThread = new Thread(new Runnable() {

                @Override
                public void run() {
                    while (!sThread.isInterrupted()) {
                       //do something
                    }
                }
            });

与之前我们通过循环标记控制线程中断一样,不同在于之前我们将标记设为false,这里我们调用interrupt方法。

这个时候我们的疑问就在于,如果是这样,那么之前我们通过循环标记来控制中断可能遇到的问题,现在不是依然还会遇到吗?
看上去的确如此,但毕竟实践才能出真知。所以我们将之前“循环标记并非万能”一节中的用例中的代码修改如下:

public class Demo {

    private static Thread sThread;
    private static boolean KEEP_RUNNING = true;

    public static void main(String[] args) {
        sThread = new Thread(new Runnable() {

            @Override
            public void run() {
                while (KEEP_RUNNING) {
                    System.out.println("Thread is beginning");
                    try {
                        Thread.sleep(5000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    for (int i = 1; i <= 5; i++) {
                        System.out.println(i + "==>"
                                + "the thread is running...");
                    }

                }
            }
        });
        sThread.start();

        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        stopThread();

    }

    private static void stopThread() {
        System.out.println("we gonna stop sThread...");
        sThread.interrupt();
    }
}

截取部分程序的输出结果:

Thread is beginning
we gonna stop sThread…

java.lang.InterruptedException: sleep interrupted
at java.lang.Thread.sleep(Native Method)
at Demo1$1.run(Demo1.java:16)
at java.lang.Thread.run(Thread.java:619)

1==>the thread is running…
2==>the thread is running…
3==>the thread is running…

注意输出结果被标记为红色的部分,由此我们注意到:当我们对线程调用interrupt方法后,抛出了一个异常。
别急,我们现在回忆一下之前通过循环标记控制线程中断的时候情况如何?是的,正常情况下我们是可以实现目的的。
而出现意外的情况是怎么样的呢?没错,正是我们在修改循环标记的时候,目标线程正处于阻塞状态当中。
那么,什么时候,线程会进入到阻塞状态当中呢?通过之前对线程状态的分析我们知道情况很多,例如线程调用了sleep,wait,join等方法。
很显然,Java的设计者们自然考虑到了这一点,既然意外的情况就出现在线程为阻塞的情况下,那么针对意外的情况作出针对就行了。
于是当我们调用interrupt方法去中断线程,Java会判断该线程是否处于阻塞,如果是则会抛出InterruptedException,并且清除之前设置的中断状态。
这自然也就是为什么,我们在代码中使用sleep,wait,join等方法时,编译器必须要求我们处理编译时异常InterruptedException的原因了。

到了现在,我们要做的实际上就很简单了。既然通过标记控制中断,会在线程阻塞时出现意外;
但是,如果对处于阻塞状态的线程调用interrupt方法又会抛出异常,那么,我们只要在异常中作出处理让线程中断就搞定了。修改异常处理的代码:

                    try {
                        Thread.sleep(5000);
                    } catch (InterruptedException e) {
                        return;
                    }

再次运行程序,我们查看输出结果,就会发现线程已经正常中断了:

Thread is beginning
we gonna stop sThread…

于是,我们在这里总结一下interrupt最常见的两种使用方式:

  • 通过isInterrupted()作为while循环的条件,配合interrupt()可以控制线程的中断。
  • 而如果想要强行将某个处于阻塞状态的线程从阻塞状态中唤醒,实际上也可以通过interrupt()方法,不过记得处理异常。

如此,我们就对中断线程的常见方式都有了了解。得出结论:通过控制循环标记并合理配合interrupt方法的使用,能够最大程度保证线程的正常中断。
但是!这样做依然也并不能够保证线程绝对能够被正常中断。归根结底还是在于Java的多线程的原理是CPU的随机切换。
也就是说,也很可能会存在下面这样的情况:

            @Override
            public void run() {
                while (KEEP_RUNNING) {
                    System.out.println("1");
                    System.out.println("2");
                    System.out.println("3");
                    System.out.println("4");
                    System.out.println("5");
                    System.out.println("6");
                    System.out.println("7");
                    System.out.println("8");
                    System.out.println("9");
                }
            }

我们要知道在以上的代码中,我们没有使用任何可能让线程进入阻塞状态的代码。但问题在于,线程仍然可能在执行过程中被切换。
即可能出现当输出到“5”的时候,CPU突然进行了一次切换工作,开始另一个线程的执行。
那假设我们在另一个线程中将标记设置为false,那么回到该线程时仍然会执行完剩下的“6到9”的输出语句,并且显然这个时候interrupt也不能解决。
这个时候没有其它办法,我们自然还得通过并发的好兄弟同步锁等方式来解决这些问题。所以总的来说,并发编程还是很复杂和让人挠头的东西。
没有捷径可走,也只能通过不断的学习,不断的在实际使用中积累错误和教训,汲取别人使用的经验,才能慢慢提高。

【Java并发编程】之二:线程中断(含代码) 转载请注明出处: 使用interrupt()中断线程     当一个线程运行时,另一个线程可以调用对应的Thread对象的interrupt()方法来中断它,该方法只是在目标线程中设置一个标志,表示它已经被中断,并立即返回。     下面一段代码演示了休眠线程的中断 public class SleepInterrupt extends Object implements Runnab 阅读详情

相关推荐

浅谈Java并发编程中断的哲学

文章摘要: 本文探讨了Java并发编程中线程中断的实现与最佳实践。作者SharkChili指出Java采用协作式中断机制,通过标识位通知线程主动停止,而非强制中断。文章解析了线程阻塞的三种场景(IO等待、休眠、锁竞争)及底层Linux中断实现逻辑。针对中断处理,提出两种方案:不具备处理能力时向上抛出异常;无法抛出时捕获中断并清理资源后标记线程中断。实践部分展示了基于volatile标识的自定义中断方案,并指出其在阻塞操作中的局限性。最后通过代码示例对比了两种方案的效果,强调合理处理中断对系统健壮性的重要性。

禅与计算机程序设计的艺术 1414

摆平Win2008与VPC2007的诡异冲突

摆平Win2008与VPC2007的冲突          话说上个周末,参加完51CTO组织的虚拟化技术沙龙,俺和老方,老胡,小废物等人杀奔西直门的红顶老汉烧鸡公,席间觥筹交错,一顿狂磋。说句题外话,这个鸡的味道真是不错,想想还要流口水,忍不住憧憬一下,啥时候还开技术沙龙啊!酒足饭饱,回到家中,看看时间也不早了,该干点正经事了,睡觉!“且慢,现在就睡觉,你睡得着吗?”,“为什么睡不着?”,“还...

weixin_33873846的博客 171

Java并发编程的艺术(五)——中断

什么是中断?在Java中没有办法立即停止一条线程,然而停止线程却显得尤为重要,如取消一个耗时操作。因此,Java提供了一种用于停止线程的机制——中断。 中断只是一种协作机制,Java没有给中断增加任何语法,中断的过程完全需要程序员自己实现。若要中断一个线程,你需要手动调用该线程的interrupted方法,该方法也仅仅是将线程对象的中断标识设成true;接着你需要自己写代码不断地检测当前线程的标识位

大闲人柴毛毛 4628

℃江让您从精通到入门:20步,写出一个详细的适配器(Adapter)

详细过程都在代码里!!!package com.dujiang.realproject.adapter;import android.content.Context; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.Ba

℃江 2万+

Java并发编程基础篇(一)之线程

前言 并发编程的目的是为了让程序运行得更快,但是,并不是启动更多的线程就能让程序最 大限度地并发执行。在进行并发编程时,如果希望通过多线程执行任务让程序运行得更快,会 面临非常多的挑战,比如上下文切换的问题、死锁的问题,以及受限于硬件和软件的资源限制问题。这一块内容也是面试核心考点之一,所以博主将以线程为起点,从0到1一起与小伙伴们走去Java并发编程之路上走一遭! 正文 进程?线程?傻傻分不清? 何谓进程 进程通常是程序、应用的同义词。进程的本质是一个正在执行的程序,程序运行时系统会创建一个进程,并且给每

weixin_48013460的博客 2686

Window10 intel realsense D435安装并实现opencv显示realsense读取的彩色和深度数据(QT+openCV+rsD35)

(1)点击"官方指南" 来到下载页,-&gt;最新的稳定版本发布 (本人下的2.16.5,现在最新2.17.0) 不需要做开发,只要下载Intel RealSense Viewer就好,这个就是相机的可视化界面,简洁明了。对应的安装包是Intel.RealSense.Viewer.exe。 本人的毕设要用到深度图做开发,所以安装Intel.RealSense.SDK.exe,SDK...

Pabebe的博客 1万+

java多条件判断_Java中,&&与&,||与|的区别 , == 比较的是什么?

java的逻辑运算符:1 . &&和&都是表示与,区别是&&只要有一个条件不一样就是不满足,如果第一个条件就是不满足就不判断后面的条件。而&要对所有的条件都进行判断。看下面的程序:输出的是“没有报错”。而将&&改为&就会如下错误:Exception in thread "main" java.lang.ArithmeticEx...

weixin_39650756的博客 8105

STM32F407+LWIP实战:手把手教你移植mbedtls库实现Modbus TCP双向认证

本文详细介绍了如何在STM32F407微控制器上移植mbedtls库,结合LWIP协议栈实现Modbus TCP的双向认证功能。通过TLS 1.2加密通道,有效提升工业物联网通信的数据安全性,涵盖证书管理、内存优化及性能调优等关键步骤,为嵌入式系统开发者提供了一套完整的解决方案。

weixin_28721917的博客 516

毛毛最新推荐伤感日志:我是一个任性的孩子

毛毛最新推荐伤感日志:我是一个任性的孩子 — 毛毛最新推荐伤感日志:我是一个任性的孩子 也许 我是被妈妈宠坏的孩子 我任性 我希望 每一个时刻 都象彩色蜡笔那样美丽 我希望 能在心爱的白纸上画画 画出笨拙的自由 画下一只永远不会 流泪的眼睛 一片天空 一片属于天空的羽毛和树叶 一个淡绿的夜晚

roarjzpro的专栏 1207

使用SSE流式输出(Javaweb前后端实战)

SSE(Server-Sent Events)是一种在Web应用中实现单向实时通信的技术。通过SSE,服务器可以主动向客户端发送更新,而无需客户端不断发起请求。这对于需要实时更新的应用场景(如聊天应用、实时数据监控等)非常有用。(服务端单向传输客户端,长连接)

记得开心一点嘛的博客 1万+

通过ssh进行宇树g1机器人进行连接

原因:就是g1机器人输出接口损坏,无法连接外部显示器。前期准备:本文电脑是联想Y7000p(windows)2.进入页面后:3.出现是一个压缩包,解压后:4.安装时:要注意,需要在文件夹中找到这个文件目录,然后在此鼠标右键开启终端进行安装:接着按照提示next下去即可,可以自定义安装路径。

m0_72207463的博客 1282

并发编程之LockSupport的 park 方法及线程中断响应

并发编程之LockSupport的 park 方法及线程中断响应

yemuxiaweiliang的博客 3148

基于RYU+Mininet的SDN校园网络实战:从零搭建虚拟化实验环境

本文详细介绍了如何利用RYU控制器和Mininet搭建SDN校园网络实验环境,从Ubuntu虚拟机准备到网络拓扑设计,再到关键网络功能实现。通过实战案例展示SDN在校园网络中的应用优势,包括简化配置、提升效率等,为网络工程师和学生提供了一套完整的虚拟化实验方案。

weixin_30872499的博客 455

并发编程 —— 谈谈线程中断

如何中断一个线程,肯定不会使用 stop。而是使用 interrupt 方法。同时,我们知道,中断一个线程只是打个标志位。不会真的中断线程,但,如果线程是阻塞状态的呢?而 Java 中,想要阻塞一个线程有很多种方式。Lock当然上面都是很简单的说说,API 并不是那么的详细。像 Lock 的 api 就有响应中断的。还有 Thread.sleep()。这个大家都知道,肯定是响应中断的。下面就来解决我们的问题。

2401_84215240的博客 1033

无实习经验?IT应届生简历封神思路:把校园经历写成offer收割机

摘要: IT应届生无实习经历如何打造竞争力简历?本文揭秘“无实习简历封神指南”,通过四大步骤将校园经历转化为HR认可的硬核技能: 素材挖掘:课程设计、个人项目、社团活动、竞赛证书都是隐藏的“实战经验”,用STAR法则细化成果。 技能转化:匹配岗位JD关键词,用“动词+量化结果”包装经历(如“优化查询效率30%”)。 避坑指南:避免流水账、夸大技能或堆砌无关经历,聚焦技术能力与岗位需求。 核心逻辑:HR看重潜力而非经验,用校园经历证明学习能力、问题解决能力和技术落地能力。 无实习≠无竞争力,学会“翻译”经历,

通俗易懂学IT 420

【2024年5月备考新增】《2024高项论文精华版(5)项目工作绩效域和度量绩效域》

3、专注于工作过程和能力。③专注于工作过程和能力。1、制定有效的度量指标。2、度量内容及相应指标。3、展示度量信息和结果。4、管理沟通和参与。7、监督新工作和变更。①制定有效的度量指标。②度量内容及相应指标。③展示度量信息和结果。5、基于度量进行诊断。

Else 的博客 1265

Java线程中断

1.什么是中断机制? 2.中断的相关API方法之三大方法说明 3.如何停止中断运行中的线程? 4.当前线程中的中断标识为true,是不是线程就立即停止? 5.关于静态方法Thread.interrupted()方法,谈谈你的理解

qq_45996900的博客 3622

使用MATLAB进行灰色预测 GM(1,1)

使用MATLAB进行灰色预测 GM(1,1)

Hou_____的博客 997

Java并发编程实战————恢复中断

中断是一种协作机制,一个线程不能强制其他线程停止正在执行的操作而去执行其他操作。 什么是中断状态? 线程类有一个描述自身是否被中断了的boolean类型的状态,可以通过调用 .isInterrupted() 方法来查看。官方解释如下: 简单来说,这个方法如果返回 true ,那么表示线程已经被中断。 恢复中断 这里提到的 “恢复中断” 绝对不是 “从中断中恢复” 的意思! 在《Ja...

Morty的技术乐园 2251

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

【Java并发编程之美 | 第一篇】并发编程线程基础

并发编程线程基础

踢桃的成长之路 1395

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

【JAVA-Day83】线程中断

欢迎来到默语博客!今天我们将深入探讨线程插队的概念,并探讨在Java中如何实现线程的中断。我们将详细介绍线程中断的概念、使用场景以及相关面试题,让你轻松掌握这一重要知识点。让我们开始吧!在多线程编程中,线程中断是一种线程之间协作的机制,用于在一个线程执行特定任务之前先执行另一个线程的现象。通常情况下,线程中断用于实现优先级任务的执行顺序控制或者某些条件的等待和唤醒。具体来说,当一个线程需要在另一个线程执行完特定任务后再执行时,可以通过线程中断来实现。

沉淀所学,分享所思,让热爱与成长同行。商务记录AI实战经验,助力开发者快速成长。 热爱AI,希望做出有影响力的技术成果。 技术点亮生活,分享连接价值与机会。 专注AI落地实战,陪你走好技术每一步。 2万+

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

Java并发编程学习12-任务取消和线程中断

《任务取消》由于篇幅较多,拆分了两篇来介绍各种实现取消和中断的机制,以及如何编写任务和服务,使它们能对取消请求做出响应。

Huazie 815

JAVA线程中断

在java中,我们想要可以使用interrupt()方法来将目标线程的中断标志位置为true,但此方法不会立即停止线程运行,需要目标线程配合。在目标线程正常运行状态时,调用interrupt()可以正常将目标线程的中断标志位置为true。在目标线程阻塞状态时,调用interrupt()会出现异常并使得目标线程的中断标识位重新变为false。我们也可以使用volatile变量或者原子类实现线程中断。

weixin_54225397的博客 1171
上一篇: Java断点续传实现原理很简单
下一篇: 一步步理解Android事件分发机制
LaterEqualsNever
博客等级 码龄12年 297粉丝 61原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值