停止线程

创建“停止标记”,thread.interrupt()

准确的说interrupt()方法只是“告知线程该停止了”,而线程检查到该“告知”后,再通过其他的办法停止线程。

线程调用了interrupt()方法只是打了一个停止标记,并不会立即停止。

当程序运行时,如果调用Thread类中的以下两个方法:

Thread.interrupted()或Thread.isInterrupted()时,可以检查当前线程的“停止标记”,

Thread.interrupted():测试当前线程是否有“停止标记”,如果有,则返回true,然后“消除该标记”。

Thread.isInterrupted():测试当前线程是否有“停止标记”,如果有,则返回true。

我们可以在run方法的需要停止处轮寻Thread.isInterrupted(),当返回true时,使用以下办法停止线程。

停止线程的方法

1、异常法。

先判断interrupted()状态,返回true后可以抛出异常,运行完catch后就会停止当前线程。

建议使用此种方式终止线程,因为可以向上抛异常,使线程终止事件得以传播。

2、thread.stop()

stop方法已经作废了,原因如下:

(1)线程调用stop后会被直接停止,根本无法确定被停止的线程运行到了什么地方,有可能一些必做的工作还没做完就被停止了。

(2)线程调用stop方法会“释放该线程持有的所有锁”,无法保证原子性。

即,假设该线程正在执行一个上锁的代码块,既然是上了锁的,那么该代码块就应该都由该线程来执行。

可此时该线程的stop方法被调用了,那么停止了该线程的执行后,锁也被释放了,别的线程就可以再执行这个上锁的代码块,可刚刚该代码块已经执行了一半了,那么此时就无法保证锁的原子性了。

3、return

先判断interrupted()状态,返回true后可以使用return语句,停止线程。

暂停与唤醒线程

thread.suspend()与thread.resume()

suspend额resume目前已作废,

原因如下:

1、在线程调用suspend时,线程如果在执行“非上锁的代码块”,则此时其他线程也可操作并改变该代码块的内容。

那么当该线程在恢复时,其之前的内容很有可能已经被修改了,从而导致数据不同步。

2、在线程调用suspend时,线程如果在执行“上锁的代码块”,则会导致锁被独占了,

因为拿着锁暂停,别人又访问不了。

object.wait()与object.notify()

之前说的suspend是线程中的方法,而wait是Object类中的方法,也就是每个对象中都拥有的方法。

object.wait()与object.notify()要与synchronized搭配的使用(下面的锁小节会详细介绍synchronized锁)。

简而言之synchronized是对某一个“对象上锁”,每次线程访问同步代码块时,都要先尝试获取该对象的锁。

wait()方法会使当前线程释放对象锁,然后当前线程“进入等待队列”,直到再次被唤醒。

notify()方法“随机唤醒”等待队列中“同一个对象锁”的一个线程。

notifyAll()方法会唤醒等待队列中“同一个对象锁”的“所有线程”。

object.wait()与object.notify()成功的弥补了之前suspend的问题。

1、object.wait()与object.notify()都要写在“同一个锁的synchronized代码块”中。

当前线程在执行同步代码块时,并执行其中的对象锁的wait方法时,当前线程会释放掉该对象锁,并且该线程进入等待状态。

然后其他线程可能会继续运行该同步代码块,当在同步代码块中执行了对象锁的notify方法时,会唤醒某条等待中的线程。

二者在同一代码块中,且wait需释放锁很好理解。因为如果 wait后线程不释放锁,那么其他线程永远没机会执行该代码块,也就永远没机会执行notify方法,也就没法唤醒该线程了。

二者在同一代码块中,解决了suspend的数据不同步问题。

锁对象调用wait后,线程释放锁,解决了suspend的独占锁问题。

2、即使调用了notify方法,当前线程也不会立即释放锁对象,“必须执行完毕同步代码块后(即退出synchronized代码块后)”,当前线程才会释放锁,(而wait方法是“一调用就立即释放锁”)

condition.await()与condition.signal()

比wait()方法更优,可以做到选择性唤醒“。

用法与object.wait()与object.notify()类似。

Lock对象相当于“对象锁”,

condition相当于“一个对象锁里的对象监视器”,一个对象锁可以有多个对象监视器。

同一把“对象锁”的同步代码块中,

可以在“某一个condition”处暂停,然后再专门唤醒该“condition”。

而synchronized就相当于:整个Lock对象锁中只有一个condition“对象监视器”。

(如某个Lock代码块中,因为只有一个condition,所以每次暂停后,唤醒的肯定还是该监视器所处线程)

Thread.sleep()

使“当前线程”暂停执行,暂停时间为“指定的毫秒数”。

一调用该方法,当前线程就会暂停,然后cpu就会去执行别的线程了。

Thread.yield()

暂停“当前线程”,“但暂停时长不确定”。

生产者消费者模式

等待通知模式的经典案例。

主测试线程

public class Main {

    //测试

    public static void main(String[] strings){

        //创建锁

        final String lock = new String("");

        //创建一条生产者线程,用于操作生产者对象

        final Producers producers= new Producers();

        new Thread(new Runnable() {

            @Override

            public void run() {

                while (true)

                    producers.setValue(lock);

            }

        }).start();

        //创建一条消费者线程,用于操作消费对象

        final Consumer consumer= new Consumer();

        new Thread(new Runnable() {

            @Override

            public void run() {

                while (true)

                    consumer.getValue(lock);

            }

        }).start();

    }

}

线程间操作的值:

//线程间操作的值

public class ValueClass {

    public static String value = "";

}

生产者:

//生产者对象,目的是产生某个值给消费者用。

public class Producers {

    public void setValue(Object lock){

        try {

            synchronized (lock){

                //“第一步”,如果当前value中有值,就等待(有值就不造值了,等该值被消耗了再造),没值就造值。

                if (!ValueClass.value.equals("")){

                    lock.wait();

                }

                //“第二步”,造出当前时间戳,并赋值给value供消费者消费

                String value = System.currentTimeMillis()+"";

                ValueClass.value = value;

                System.out.println("生产者已生产时间戳:"+value);

                //“第三步”,通知等待消费的消费者,可以消费了

                lock.notify();

            }

        }catch (InterruptedException e){

            e.printStackTrace();

        }

    }

}

消费者:

//消费者对象,目的是获取某个生产者生产的值

public class Consumer {

    public void getValue(Object lock){

        try {

            synchronized (lock){

                //“第一步”,如果没有值,就等待(等待生产者造值)

                if (ValueClass.value.equals("")){

                    lock.wait();

                }

                //“第四步”,从ValueClass中消费值,并将Class中的值赋值为"",表示消费完了。

                System.out.println("消费者消费了时间戳:"+ValueClass.value);

                ValueClass.value = "";

                //“第五步”,通知生产者,表示你可以接着造值了(又回到第二步)

                lock.notify();

            }

        }catch (InterruptedException e){

            e.printStackTrace();

        }

    }

}

结果:

其它操作

thread.join()

主线程创建子线程,如果主线程想确保子线程运行完后再结束,就可以用到join方法了。

join()方法的作用是“等待线程对象销毁

java 线程操作的更多相关文章

  1. java线程操作

    目录 前言 创建多线程的方式 1继承thread抽象类 2实现Runnable接口 3实现Callable接口 匿名内部类 线程池 线程安全 同步代码块 同步方法 锁机制 线程状态 前言 进程:内存运 ...

  2. JAVA线程操作常见面试题 包括不使用内部类对多个线程加减1

    class ManyThreads2 { private int j = 0; public synchronized void inc() { j++; System.out.println(Thr ...

  3. Java线程状态及切换

    Java线程状态及切换 一.什么是Java线程状态 在Java程序中,用于描述Java线程的六种状态: 新建(NEW):当前线程,刚刚新建出来,尚未启动. 运行(RUNNABLE):当前线程,处于竞争 ...

  4. Java基础-线程操作共享数据的安全问题

    Java基础-线程操作共享数据的安全问题 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.引发线程安全问题 如果有多个线程在同时运行,而这些线程可能会同时运行这段代码.程序每次运 ...

  5. java 线程 原子类相关操作演示样例 thinking in java4 文件夹21.3.4

    java 线程  原子类相关操作演示样例 package org.rui.thread.volatiles; import java.util.Timer; import java.util.Time ...

  6. Java基本的线程操作(附代码)

    啦啦啦啦,从头整理一遍java并发的内容.开始是基本的线程操作 线程状态切换: 新建线程: @Test public void newTread(){ Thread t1 = new Thread(n ...

  7. Java多线程操作同一个对象,线程不安全

    Java多线程操作同一个对象 发现问题:多个线程操作同一资源的情况下,线程不安全,数据紊乱 代码: package multithreading; // Java多线程操作同一个对象 // 买火车票的 ...

  8. Java 线程常用操作

    继Java线程生命周期继续学习Java线程其他常用操作 线程的常用操作 设置线程名字:setName() 获取线程名称:getName() 线程唯一Id:getId() // 自定义线程名称 Stri ...

  9. 2.2多线程(java学习笔记)线程状态及线程操作的相关方法

    一.线程的状态 线程一般具有五种状态,即创建.就绪.运行.阻塞.终止. 它们之间的关系: 二.线程操作相关方法 1.设置和取得线程名称. 如果不设置线程名称,系统会自动分配线程名,一般格式为Threa ...

随机推荐

  1. 创建servlet程序知识点详解---servlet-day03

    #1.表单包含有中文参数值,如何处理? ##(1)为什么会有乱码? 表单提交时,浏览器会对中文参数值进行编码/ 注:会按照表单所有的页面打开时所使用的字符集进行编码 比如,浏览器会使用utf-8对中文 ...

  2. dotnet core命令

    dotnet run -----运行程序 dotnet publish -r centos-x64  -----发布程序 mkdri 文件名--->cd 文件名--->dotnet new ...

  3. Windows 服务器自动重启定位

    有个非常好的小技巧,就是在服务器端命令行,执行systeminfo,能查到服务器上一次重启的时间,依照这个时间在Event Log里再找相应的日志就容易多了. 补充:还能查到这台服务器是虚拟机还是实体 ...

  4. 2019/4/8 wen text

    构造器产生对象的步骤:1.为对象在内存中申请内存空间. 2.对对象的属性申请内存空间. 3.为属性进行初始化. 4.执行构造器中编写的其他代码. 静态方法调用:    类名.方法 非静态方法调用:  ...

  5. QQ"坦白说"抓包破解与PacketCapture使用介绍

    据腾讯发布内容来看,“坦白说”是刚刚在QQ中上线的新功能,还在测试阶段就已经非常火爆. 但作为一种web端的小游戏,无疑可以使用爬虫的来自我模拟. (话说写完这篇的时候我总感觉自己几年前好像写过这个. ...

  6. 剑指offer(20)包含min函数的栈

    题目描述 定义栈的数据结构,请在该类型中实现一个能够得到栈最小元素的min函数. 题目分析 首先一开始我们分析得到最小值肯定要比较嘛,和栈里面的数据一一比较,但是栈这种数据结构,你又只能和栈顶弹出来的 ...

  7. WinForm中预览Office文件

    WinForm预览Office文档 使用WinForm, WPF, Office组件 原理:使用Office COM组件将Word,Excel转换为XPS文档, 将WPF的DocumentViewer ...

  8. 第十届蓝桥杯2019年C/C++ 大学B组省赛试题

    2019年第十届蓝桥杯大赛软件类省赛C/C++大学B组 试题 A:组队 本题总分:5分 [问题描述] 作为篮球队教练,你需要从以下名单中选出 1号位至 5号位各一名球员, 组成球队的首发阵容. 每位球 ...

  9. 论文笔记:Real-Time MDNet

    Real-Time MDNet ECCV 2018  2018-10-22 15:52:01 Paper:http://openaccess.thecvf.com/content_ECCV_2018/ ...

  10. NodeJS:(一)特性&环境&测试

    特性: ①非阻塞I/O,事件驱动,单线程 非阻塞I/O:进程不等I/O完成(阻塞是等I/O完成后才进行下一步) 事件驱动:异步操作结束后通知 ②优点 前端职责范围变大,统一开发体验 处理高并发(单位时 ...