博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
java 多线程
阅读量:5132 次
发布时间:2019-06-13

本文共 8252 字,大约阅读时间需要 27 分钟。

10

Java线程状态

NEW ---状态是指刚创建 , 尚未启动。
RUNNABLE --- 状态是正在正常中 , 当然可会有某时 /IO待的操作 /CPU时片切换 ,这个状态下发生的等待, 不是 , Sleep。
BLOCKED ---这个 个状态下 , 是在多个有同步操作的场景 , 比如正在待另一个的 synchronized 块的执放
WAITING --- 个状态下是指拥有了某个之后 , 用了他的 wait方法, 待其他 /拥有用 notify / notifyAll
TIMED_WAITING --- 个状态就是有的 (时制 )的WAITING, 一出现在用 wait(long), join(long)情况下 ,
另外一个 sleep后, 也会入 TIMED_WAITING状态
TERMINATED --- 个状态下 的 run方法已执完毕了 , 基本上就于死亡了。

线程的状态

 

首先新建一个线程,然后启动,启动后变成runnable状态,表示已经准备就绪可以执行了,或者正在执行当中。执行完了后终止。

blocked:访问临界区,如果拿不到临界区的资源,需要等待。被动的等待。

waiting:主动发起的等待。自己的数据没准备好。

timedwaiting:限时等待。跟waiting相似。这个有时间限制,比如设置5秒钟。不管5秒内数据有没有准备好,都执行。waiting是不限时间的等待。

线程的基本操作

Thread t1 = new Thread(){   //新建线程            @Override            public void run(){                System.out.println("hello");            }        };        t1.start();  //启动线程,run方法被执行
Thread t1 = new Thread();t1.run();//在当前线程中执行。不是另外开启的线程。要想异步,必须start

不用重载run方法。使用Runable接口实现。

public class testRunable implements Runnable{    public static void main(String[] args) {        Thread t1 = new Thread(new testRunable()); //传入参数的模式。一般推荐        t1.start();    }    @Override    public void run() {        System.out.println("OK");    }}

终止线程

Thread.stop();//不推荐使用。他会释放所有的monitor。有可能一个类中其他赋值还没有完成就停止了。这样就造成数据不同步,把对象写坏。会释放锁

中断线程,写一个支持中断的线程,可以有效的控制数据不被写坏。

t1.interrupt();//中断线程Thread.currentThread().isInterrupted(); ///判断是否被中断Thread.currentThread().interrupted();//判断是否被中断,并清除当前中断状态。

sleep 线程睡眠。释放cpu。抛出异常后,会清除中断标记位,所以需要在抛出异常的时候,再次中断。

public void run() {        // TODO Auto-generated method stub        while(true){            if(Thread.currentThread().isInterrupted()){ //线程被中断 退出                break;            }            try {                Thread.sleep(20000); //如果睡眠被中断,就会醒来            }            catch(InterruptedException e){  //抛出异常后,会清除中断标记位                System.out.println("interrupted when sleep");                 Thread.currentThread().interrupt(); //设置中断  这样 当再次回到while循环的时候,就能判别有没有被中断。                            }            Thread.yield();        }    }}

挂起 suspend和 继续执行resume。这两个方法都是被废弃的。

suspend不会释放锁

如果枷锁发生resume之前,会发生死锁。

等待线程结束 join和谦让yeild

public class JoinMain {    public volatile static int i = 0;    public static class AddThread extends Thread {        @Override        public void run() {            for (i = 0; i < 1000000; i++);        }    }    public static void main(String[] args) throws InterruptedException {        AddThread at = new AddThread();        at.start();        at.join(); //主线程停止执行,等待线程执行完,再打印i的值        System.out.println(i);    }}

join的本质

while (isAlive()){ //判断当前线程还活着,当线程执行完毕后,系统会调用 notifyAll()   wait(0); //调用wait方法} //不要在Thread实例上使用wait() 和notify()方法 这样会干扰jdk内部实现。

synchronized 用来管理和控制临界区。

-给指定对象加锁:给指定对象加锁。进入同步代码前要获得给定对象的锁

-给实例方法加锁:相当于对实例加锁。进入同步代码前要获得当前实例的锁

-给静态放假加锁:相当于给当前类加锁。进入同步代码前要获得当前类的锁

public class SynchronizedTest extends Thread {    public Object instance;    public static int i;    @Override    public void run(){        for(int j=0;j<100000;j++){            //指定枷锁对象 一次只有一个线程            synchronized(instance){                i++;            }        }    }    //用在方法上  表示increase所在的对象上加锁  如果每次生成不同的实例,这个锁是没有用的    public synchronized void increase(){        i++;    }    // 表示给increase2 所在的类上加锁 。就算有不同的锁也可以锁住,因为类只有一个    public static synchronized void increase2(){        i++;    }}
public class Accounting implements Runnable {    static Accounting instance = new Accounting();    static int i=0;    //锁加载Accounting类上  是可以锁住的    public synchronized static void increase(){        i++;    }
//    锁加在instance实例上  也是可以锁住的  输出2000000//    public synchronized  void increase(){//        i++;//    }
@Override    public void run() {        for (int j=0;j<1000000;j++){            increase();        }    }    public static void main(String[] args) throws InterruptedException{        Thread t1 = new Thread(instance);        Thread t2 = new Thread(instance);        t1.start();t2.start();        t1.join(); t2.join();        System.out.println(i);  //运行结果,输出2000000          }}
public class Accounting implements Runnable {    static Accounting instance = new Accounting();    static int i=0;    //锁加在instance实例上     public  synchronized  void increase(){        i++;    }    @Override    public void run() {        for (int j=0;j<1000000;j++){            increase();        }    }    public static void main(String[] args) throws InterruptedException{        Thread t1 = new Thread(new Accounting()); Thread t2 = new Thread(new Accounting());        t1.start();t2.start();        t1.join(); t2.join();        System.out.println(i);  //因为初始化了不同的实例 所以是锁不住的  需要把increase 改成static    }}

Object.wait() 让线程等待。一般是数据没有准备好,所以等待

Object.notify() 通知在这个对象上等待的线程,可以继续工作了。不用再等待了。 如果有多个等待的线程,会随机先通知一个。

public class wnTest {    public Object object = new Object();    public class wn2 extends Thread {        public void run(){            synchronized(object){                System.out.println(System.currentTimeMillis()+" :wn2 start!notify one thread");                object.notify();                System.out.println(System.currentTimeMillis()+" :wn2 end!");                try {                    Thread.sleep(2000);                } catch (InterruptedException e) {                    e.printStackTrace();                }            }        }    }    public class wn1 extends Thread {        public void run(){            synchronized(object){                System.out.println(System.currentTimeMillis()+" :wn1 start!");                try {                    System.out.println(System.currentTimeMillis()+" :wn1 wait for object");                    object.wait();                                    } catch (InterruptedException e) {                    e.printStackTrace();                }                System.out.println(System.currentTimeMillis()+" :wn1 end!");            }        }    }    public void ext(){        wn1 w = new wn1();        wn2 w2 = new wn2();        w.start();        w2.start();    }    public static void main(String[] args) {        new wnTest().ext();    }}
//执行结果1498404259216 :wn1 start!1498404259216 :wn1 wait for object1498404259216 :wn2 start!notify one thread1498404259216 :wn2 end!  1498404261221 :wn1 end! //因为有个sleep操作,wn2不能马上执行完,导致wn1不能马上拿到锁。所以有时间差
 

线程安全

当多个线程对同一arraylist进行添加时,可能一个线程获取到的arraylist size为5 而另一个线程获取arrayList的size为3,当给arralist继续添加的时候,就会增加到第四个。但第四个已经被线程一添加过了。所以会抛出异常,而且获取的总是是小于预期的。

public class ArrayListMultiThread {    static ArrayList
al = new ArrayList
(10); public static class AddThread implements Runnable{ @Override public void run() { for (int i=0;i<1000;i++){
al.add(i); } } } public static void main(String[] args) throws InterruptedException { Thread t1 = new Thread(new AddThread()); Thread t2 = new Thread(new AddThread()); t1.start();t2.start(); t1.join(); t2.join(); System.out.println(al.size()); //抛出异常 返回小于2000的数值。 }}

包装为线程安全的

import java.util.Collections;import java.util.LinkedList;import java.util.List;import java.util.Vector;import java.util.concurrent.CopyOnWriteArrayList;public class safeArrayList {    //将list变为线程安全的方法 对于所有的集合都是通用的    static List
al = Collections.synchronizedList(new LinkedList
()); public static List
l = Collections.synchronizedList(new LinkedList
()); public static List
l2 = new Vector(); public static List
l3=new CopyOnWriteArrayList
(); public static class AddThread implements Runnable{ @Override public void run() { for (int i=0;i<1000;i++){ al.add(i); } } } public static void main(String[] args) throws InterruptedException { Thread t1 = new Thread(new AddThread()); Thread t2 = new Thread(new AddThread()); t1.start();t2.start(); t1.join(); t2.join(); System.out.println(al.size()); //2000 }}
public static Map m= Collections.synchronizedMap(new HashMap());     public static Map m2 = new ConcurrentHashMap();
ConcurrentHashMap的性能高于Collections.synchronizedMap。因为ConcurrentHashMap不是锁整个hashmap。而是把hashmap继续分成16个segments,每一个segments都是一个hashmap,每一次对它操作的时候,不需要锁整个对象,当有一个对象进来后,先锁整个对象,再查落在哪一个segments,然后锁单个segments就行。提高哦并发度。所以推荐。

 

转载于:https://www.cnblogs.com/milanmi/p/7078054.html

你可能感兴趣的文章
【python】理解循环:for,while
查看>>
python定时清空本目录下除本脚本外的全部文件
查看>>
【PHP】在目标字符串指定位置插入字符串
查看>>
【JS】jQuery设置定时器,访问服务器(PHP示例)配合微信、支付宝原生支付,跳转web网页...
查看>>
统计学的统一(1)
查看>>
实验四2
查看>>
用CSS3画出一个立方体---转
查看>>
date
查看>>
C#实现Winform间的数据交互的三种方法
查看>>
java项目中rmi远程调用实例
查看>>
5.分组函数
查看>>
java_Observer Design Pattern
查看>>
【c++编程思想】字符串
查看>>
Python入门神图
查看>>
CentOS 7.0安装
查看>>
在小程序开发的新风口 看华为云如何助立创科技抢占市场红利
查看>>
第一次博客随笔:苏钰冰
查看>>
HIS-DELPHI-读取数据库配置
查看>>
如何引入iconfont图标与Element-UI组件
查看>>
获取Model的所有属性字符串
查看>>