停止线程

创建“停止标记”,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. [iOS] 测试设备解决自签名证书问题

    不多说,解决过程都是泪. 用了最简单粗暴的方式. 1. 将你的自签名证书,放到测试设备可以访问的站点上 2. 用safari访问上面的地址,直接将证书安装到本设备上 搞掂! Have fun with ...

  2. OpenStack-Neutron-VPNaaS-API

    1 命令 1.1 IKE策略 vpn-ikepolicy-create Create an IKEPolicy vpn-ikepolicy-delete Delete a given IKE Poli ...

  3. C#-MVC-Razor视图引擎及解决路径问题的三个方法

    Razor 视图引擎 与Aspx开发区别在于代码: 1.Razor 更智能,摒弃了<%%>格式,直接用@符号开启cs代码,遇到html时自动识别 2.遇到如汉字等即非cs代码,又非html ...

  4. python locust 性能测试:locust 关联---提取返回数据并使用

    from locust import HttpLocust, TaskSet, taskimport jsonfrom common import readConfig class UserBehav ...

  5. Atlassian JavaScript load error(配置Atlassian的时候报无法加载script文件)

    等我弄好的时候,发现报错的图已经成为历史了,所以就没有截图了. Atlassian JavaScript load error We tried to load scripts but somethi ...

  6. js cookie缓存处理

    function setCookie(cnameList,cvalueList,exdays){ var d = new Date(); d.setTime(d.getTime()+(exdays*2 ...

  7. Redis学习-hash数据类型

    hash 类型是string类型的field和value的映射表,或者说是一个string集合,适合存储对象,相比较而言,将一个对象类型存储在hash类型里要比存储在string类型里占用更少的内存空 ...

  8. JAVA值传递之基本数据类型和引用数据类型

    #1.基本数据类型值传递 package 经典小Demo.值传递; public class Test { public static void main(String[] args) { int a ...

  9. mysql5.6 centos编译部署

    准备工作 创建用户 useradd mysql 删除老版本 rpm -qa |grep mysql rep -e mysql包 重命名默认的mysql配置文件 mv /etc/my.cnf /etc/ ...

  10. Oracle11g导出为Oracle10g版本数据,解决10g不兼容11g文件

    EXPDP USERID='JCSJ/JCSJ@FZBD' schemas=JCSJ directory=bac_file dumpfile=JCSJ.dmp logfile=JCSJ.log ver ...