JAVA并发Day2 (并行程序基础)

版权声明:版权为ZZQ所有 https://blog.csdn.net/qq_39148187/article/details/81985930

进程和线程

https://www.cnblogs.com/tiankong101/p/4229584.html

https://www.cnblogs.com/dreamroute/p/5207813.html

java 中的线程会被映射到操作平台上,

进程 的调度可以说对于操作系统是一个大的调度,线程是进程中的执行单元

在java 中创建一个线程jvm 会把线程映射到window 进程上去,

线程状态

调用start 方法才可以使用,进入runnable 状态,说这个线程是可以执行了,但是并不表示线程一定在cup执行,在jvm 层次上,我这个线程的所有工作所有的锁的申请以及相关工作到位了,但是系统本身很繁忙,cpu 没有时间, 还是不能执行,具体有没有执行取决于物理cpu 的状态,如果一个线程的所有工作做完了就会进入terminated

在线程执行的过程中有可能会申请一些锁,如果锁被别的线程占用, 申请不到锁这个线程会被挂起,如果一个线程调用waiting方法就会处于等待状态, 等待其他线程的通知, 如果被通知就会进入runnable 状态,然后继续执行,waiting 一种是无限等待一种是通过notifg方法通知线程脱离等待

Thread

开一个线程用start 方法, run方法是runable 接口的实现, 每开一个线程在java 中都要实现runable 接口中的run方法 start 方法调用的就是run方法

如果只调用run方法还是单线程的,执行run方法中的东西

Run 回到用target 然后还是runable 调用run 方法

在init 方法中要传入 runable run 方法,

  1. 重写run 方法
  2. 传递一个runable 接口的实例 ,调用thread 的一个构造方法,构造方法调用init方法

终止线程(弃用)

Stop 方法可以停止线程,到那时strop 方法被启用了,stop 方法太暴力了,如果一个线程正在工作, 直接把线程杀死, 这个时候线程会释放所有的锁(monitor)有可能会导致多线程数据的不一致性

线程正在操作共享数据的时候,突然杀死,杀死hi后就会释放锁,如果后面有等待的线程就会导致,等待线程修改数据,这个时候数据会在前面线程的基础上修改,数据不一致这种行为很难发现,没有异常,只有发现数据错误离谱才能找

如果第一个线程正在进行写操作,刚刚写了一个id,突然stop()方法把线程给杀死了,stop()杀死线程会释放锁,然后第二个线程进行读取临界区值,这时候就读取到错误的,对错误的进行操作,整个结果就错了

线程中断

public void Thread.interrupt()           // 中断线程

public boolean Thread.isInterrupted()    // 判断是否被中断

public static boolean Thread.interrupted() // 判断是否被中断,并清除当前中断状态

如果要中断线程, 会先给线程一个招呼,然后线程会自动的给自己中断点,然后到的时候就中断,

挂起(suspend) 继续执行(resume)线程

Suspend()不会释放锁

如果加锁发生在resume之前,则死锁发生

不推荐使用

如果一个线程被挂起,正在使用临界区资源,这样他不会释放锁,这样就会发生死锁,

没有办法确定 resume 发生在 suspend 之后,如果发生在suspend 之前,没有什么影响,这样线程就冻结了,其他线程拿不到锁,就死锁

Jvm 命令

Jps 查看所有进程

Jstack  调出指定的进程

等待线程结束(join)和谦让(yeild) 

static native yeild()方法

把自己使用CPU的权利释放掉,然后下次进行竞争,但是下次有可能还会被使用yeild()方法的线程抢到资源

public final void join()方法

等待其他线程结束,然后一起再运行  ,如果等待的线程结束了, 就会调用notifyAll()方法, 唤醒等待在当前对象实例上的所有的线程 

public final native void wait(long timeout)

此方法是Object类的方法, 让当前线程进行等待 

public final native void notifyAll()

此方法也是Object的 , 唤醒等待在当前对象实例上的所有的线程 

唤醒在当前线程实例上的所有线程

任意的对象实例都有这些方法,因为方法定义在object 中,应用程序不用要notifyall 和notifyall 这里的方法是会被系统调用的, notifyall 是会被系统调用的不会如我们自己所愿,notifyall  是jvm层的代码是由c++ 实现的

守护进程

在后台默默地完成一些系统性的服务,比如垃圾回收线程、JIT线程就可以理解为守护线程

当一个Java应用内,只有守护线程时,Java虚拟机就会自然退出

调用Thread 中的Daemon(true)方法传入true 就会把这个线程设置为守护线程

package com.Thread;

/**
 * @author ZZQ
 * @Title: java8_demo
 * @Package com.Thread
 * @date 2018/7/16 16:24
 * 守护线程
 */
public class ThreadDaemon {


    public static void main(String[] args) {
        Thread t = new Thread(()->{
            while (true){
                System.out.println("i am ");
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

        });
        //isDaemon 测试此线程是否为守护线程  setDaemon 把此线程添加
        t.setDaemon(true);
        t.start();

        while (true){

        }
    }

}

程序的目的就是执行我们非守护简称,辅助线程,支持程序比如  gc线程

我在读jvm 深入解析的时候有一章 就有讲到守护线程,有个例子,就是gc 线程, 

https://blog.csdn.net/qq_39148187/article/details/81984792

当时没有上代码,现在上个代码说明下

package com.jvm;

/**
 * @author ZZQ
 * @Title: java8_demo
 * @Package com.jvm
 * @date 2018/7/14 16:48
 */
public class FinalizeEscapeGC {

    public static FinalizeEscapeGC SAVE_HOOK= null;

    public void isAlive(){
        System.out.println("yes,i am still alive :)");
    }

    @Override
    protected void finalize() throws Throwable {
        super.finalize();
        System.out.println("finalize method executed!");
        FinalizeEscapeGC.SAVE_HOOK=this;
    }


    public static void main(String[] args) throws  Exception{
        SAVE_HOOK=new FinalizeEscapeGC();

        // 对象第一次拯救自己
        SAVE_HOOK =null;
        System.gc();

        //因为finalize 方法执行的优先级很低,要暂停0.5 等待他
        Thread.sleep(500);
        if(SAVE_HOOK !=null){
            SAVE_HOOK.isAlive();
        }else {
            System.out.println("no , i am dead :(");
        }

    }




}

也 就是 说一个对象如果不是可达对象, 就会被放置到一个F-Queue 的列队中,稍后由虚拟机建立一个,自己建立的,低优先级的,Finailizer线程去执行他,

线程优先级

线程优先级高的线程更有可能拿到资源执行

线程最高的优先级是10 在java 中,默认是5 ,最低的是1

设置线程的优先级 使用thread 中的方法 setPriority()  

这里的优先级是一个概率问题, 就像是lol 中的暴击率,暴击率高有可能刀刀暴击,但只是可能

线程基本同步操作

synchronized

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

– 直接作用于实例方法:相当于对当前实例加锁,进入同步代码前要获得当前实例的锁。

– 直接作用于静态方法:相当于对当前类加锁,进入同步代码前要获得当前类的锁。 、

synchronized   的底层代码是通过cpp 来实现的

1. 同步代码块

package com.Thread;

/**
 * @author ZZQ
 * @Title: java8_demo
 * @Package com.Thread
 * @date 2018/7/16 20:48
 */
public class Synchronizeddemo2 implements  Runnable{

    public static  int i = 0;




    public static synchronized  void staticmethod(){
        i++;
    }

    @Override
    public void run() {
        for (int j = 0 ; j < 100; j ++){
            staticmethod();
        }
    }




    public static void main(String[] args) throws Exception {
        Synchronizeddemo2 sy = new Synchronizeddemo2();
//        Thread t1 = new Thread(sy);
        Thread t2 = new Thread(sy);
//        t1.start();
        t2.start();
        //t1.join();
        t2.join();
        System.out.println(i);

    }

}

2. 同步静态方法

package com.Thread;

/**
 * @author ZZQ
 * @Title: java8_demo
 * @Package com.Thread
 * @date 2018/7/16 21:13
 */
public class Synchronizeddemo3 implements  Runnable {

    static  int i = 0 ;

    public static synchronized void newmethod(){
        i ++ ;
    }

    @Override
    public void run() {
        for (int i = 0 ; i<100; i ++){
            newmethod();
        }
    }


    public static void main(String[] args) throws  Exception {
        Thread t1 = new Thread(new Synchronizeddemo3());
        Thread t2 = new Thread(new Synchronizeddemo3());
        t1.start();
        t2.start();
        t1.join();
        t2.join();
        System.out.println(i);
    }


}

3. 同步方法

package com.Thread;

/**
 * @author ZZQ
 * @Title: java8_demo
 * @Package com.Thread
 * @date 2018/7/16 21:13
 */
public class Synchronizeddemo3 implements  Runnable {

    static  int i = 0 ;

    public static synchronized void newmethod(){
        i ++ ;
    }

    @Override
    public void run() {
        for (int i = 0 ; i<100; i ++){
            newmethod();
        }
    }


    public static void main(String[] args) throws  Exception {
        Thread t1 = new Thread(new Synchronizeddemo3());
        Thread t2 = new Thread(new Synchronizeddemo3());
        t1.start();
        t2.start();
        t1.join();
        t2.join();
        System.out.println(i);
    }


}

wait notify notifyall 方法

wait() 有个条件,他必须是当前线程的监视器调用,wait()会释放当前线程的监视器,等待其他线程通知

notify 也是如此,必须是当前线程的监视器调用,会随机唤醒一个wait 的线程   

{

并不是被notify()方法唤醒的线程直接就运行了,他要等待正在拿着锁的线程,等这个线程释放锁,然后他们进行竞争,拿到锁才执行

}

notify 唤醒所有等待在当前对象监视器的线程

package com.Thread;

import java.time.Duration;
import java.time.Instant;

/**
 * @author ZZQ
 * @Title: java8_demo
 * @Package com.Thread
 * @date 2018/7/16 22:04
 */
public class ThreadWaitNotify {

    public  static ThreadWaitNotify threadWaitNotify = new ThreadWaitNotify();

    public static void main(String[] args) {
        new Thread(()->{
            synchronized (threadWaitNotify){
                try {
                    // jdk8 runable 是一个函数式接口
                    Instant in =  Instant.now();
                    threadWaitNotify.wait();
                    Instant out = Instant.now();
                    Duration between = Duration.between(in, out);
                    System.out.println(between.toMillis());
                }catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }).start();


        new Thread(()->{
            synchronized (threadWaitNotify){
                try{
                    threadWaitNotify.notify(); //唤醒在当前线程实例上的随机线程
                    System.out.println("notify执行完毕........");
                }catch (Exception e){
                    e.printStackTrace();
                }
            }
        }).start();



    }


}

猜你喜欢

转载自blog.csdn.net/qq_39148187/article/details/81985930