1.2 java线程间的共享与协作

java线程中断机制

一、java线程的工作方式

java线程之间的工作方式是协作式的,需要自己手动去结束线程,获取中断标志位,进而进行处理,或者判断当前中断标志位是否是true,false就继续执行自己的业务代码,不是就直接跳出结束线程。

二、线程中断的方式

1、在主线程中调用threadObject.interrupt()方法。
2、在子线程中调用isinterrupt()来判断当前线程是否被中断了。

三、注意事项

如果方法抛出了interruptException则会将中断标志物位重制位flase。需要我们在catch中重新将标志为置为true;

四、Java线程的各种状态以及切换的方式

在这里插入图片描述

五、深入理解run方法和start方法

package cn.enjoy.controller.thread;

/**
 * @author:wangle
 * @description:启动线程
 * @version:V1.0
 * @date:2020-01-17 11:31
 **/
public class StartThread {


    public static class ThreadRun extends Thread{
        @Override
        public void run(){
            System.out.println("I'm am "+Thread.currentThread().getName());
        }
    }


    public static void main(String arg[]){
        ThreadRun threadRun = new ThreadRun();
        threadRun.setName("ThreadRun");
        threadRun.run();
    }

}

输出结果:
在这里插入图输出结果片描述
阐述:可以看到,输出的是main,所以当前执行代码块的是主线程。这是java一个面向对象的基本概念,谁调用当前代码块就是哪个线程在执行,可以明显看到是主线程调用了run方法,所以run方法被的当作了一个普通的方法

当使用start启动线程的时候,jvm才会给当前线程分配线程资源,真正的启动一个线程。

六、线程优先级

优先级为1~10,依次递减、缺省为5
使用setPriority方法进行优先级的设定,但是不同虚拟机会进行不同的处理,甚至会忽略掉设置的优先级值。所以不能在程序中太依靠当前值来控制线程优先级。

七、守护线程

threadRun.setDaemon();将线程设置为守护线程
特点:和主线程生命周期相同
finally的代码块不一定会执行,所以在守护线程中不能在finally中进行释放某些特定资源。以免资源泄漏

八、线程安全

synchronized对临界资源进行同步

1、作用于实例方法(对象锁)

a、多个线程访问同一个对象的同一个方法
public class StartThread implements Runnable {
    //共享资源
    static int i =0;
    /**
     * synchronized 修饰实例方法
     */
    public synchronized void increase(){
        i++;
    }
    @Override
    public void run(){
        for (int j =0 ; j<10000;j++){
            increase();
        }
    }

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

在这里插入图片描述
分析:当两个线程同时对一个对象的一个方法进行操作,只有一个线程能够抢到锁。因为一个对象只有一把锁,一个线程获取了该对象的锁之后,其他线程无法获取该对象的锁,就不能访问该对象的其他synchronized实例方法,但是可以访问非synchronized修饰的方法

b、一个线程获取对象锁之后其他线程来访问改对象的其他synchronized方法
public class StartThread{



    public synchronized void method1() {
        System.out.println("Method 1 start");
        try {
            System.out.println("Method 1 execute");
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("Method 1 end");
    }

    public synchronized void method2() {
        System.out.println("Method 2 start");
        try {
            System.out.println("Method 2 execute");
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("Method 2 end");
    }


    public static void main(String[] args) {
        final StartThread test = new StartThread();

        new Thread(new Runnable() {
            @Override
            public void run() {
                test.method1();
            }
        }).start();

        new Thread(new Runnable() {
            @Override
            public void run() {
                test.method2();
            }
        }).start();
    }
}

在这里插入图片描述
分析:一个对象只有一把锁,当线程1获取锁之后,其他线程需要等待1释放锁之后才能获取锁再去执行其他被同步的方法。

c、线程1获取锁之后,其他线程来访问该对象的非synchronized方法。

分析:在次不再张贴代码,只需将b中方法2去掉synchronized关键字即可。其他线程可以正常访问非synchronized的方法不需要等待1释放锁

d、当多个线程作用于不同的对象的synchronized方法

结果同c、因为锁的粒度是在对象的粒度上,非同一个对象使用的不是同一把锁。

2、synchronized作用于静态方法(类锁)

public class StartThread implements Runnable {
    //共享资源
    static int i =0;
    /**
     * synchronized 修饰实例方法
     */
    public static synchronized void increase(){
        i++;
    }
    @Override
    public void run(){
        for (int j =0 ; j<10000;j++){
            increase();
        }
    }

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

在这里插入图片描述
分析:虽然是不同的线程访问不同的对象的synchronized方法,但是由于被static方法修饰的方法是属于类本身的,所以也是被同步了。这就是类锁

3、synchronized作用于同步代码

public class synchronizedTest implements Runnable {
    static synchronizedTest instance=new synchronizedTest();
    static int i=0;
    @Override
    public void run() {
        //省略其他耗时操作....
        //使用同步代码块对变量i进行同步操作,锁对象为instance
        synchronized(instance){
            for(int j=0;j<10000;j++){
                i++;
            }
        }
    }
    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);
    }
}

必须获取到instance对象的锁才能执行代码区域的代码,所以给过也是被同步的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值