java复习并发

java复习二

想复习一下Java并发,看 Java 特种兵 并发部分 感觉讲的不错,写一下读书笔记

两个使用线程的方法

  1. 实现Runnable接口的多线程
package myList;


public class threadtest {
    public static void main(String[] args) {
        ThreadTests ds1 = new ThreadTests("阿三");
        ThreadTests ds2 = new ThreadTests("李四");

        Thread t1 = new Thread(ds1);



        Thread t2 = new Thread(ds2);

        t1.start(); 
        t2.start(); 
    } 
}

class ThreadTests implements Runnable {
    private String name;

    public ThreadTests(String name) {
        this.name = name;
    } 

    public void run() {
        for (int i = 0; i < 5; i++) {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(name + ": " + i);
        } 
    } 
}

//李四: 0
阿三: 0
李四: 1
阿三: 1
阿三: 2
李四: 2
李四: 3
阿三: 3
阿三: 4
李四: 4

2.扩展Thread类实现的多线程

package myList;


public class TestThread extends Thread {
    public TestThread(String name) {
        super(name);
    } 

    public void run() {
        for(int i = 0;i<5;i++){
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(this.getName()+" :"+i);
        } 
    } 

    public static void main(String[] args) {
        Thread t1 = new TestThread("阿三");
        Thread t2 = new TestThread("李四");
        t1.start(); 
        t2.start(); 
    } 
}

//李四 :0
阿三 :0
李四 :1
阿三 :1
阿三 :2
李四 :2
阿三 :3
李四 :3
阿三 :4
李四 :4

new Thread()操作没有完成对线程的创建,只有当调用start()方法时才会真正在系统中存在一个线程,Thread本身对应的实例只是JVM内一个普通Java对象,是一个线程操作的外壳,而不是真正的线程。

线程状态

1.NEW 状态
表示线程还没有启动,只是创建了一个Java外壳,要注意的是调用了start()方法不表示状态就立即改变。
2.RUNNABLE 状态
程序运行状态,任务也有可能处于等待状态
3.BLOCKED 状态
BLOCKED称为阻塞状态,原因通常是它在等待一个锁
4.WAITING 状态
通常是指一个线程拥有对象锁后进入到相应的代码区域后,调用相应的锁对象的wait()方法操作后产生的一种结果,与BLOCKED状态比较,BOLOCKED状态是虚拟机认为程序还不能进入某个区域,发生wait()操作的条件就是要进入临界区,只是还有一些其他配合的资源没有准备充分,所有产生了等待。
notify()方法是唤醒一个处于WAITING状态的线程
5.TIMED_WAITING 状态
Thread.sleep()就可以进入TIMED_WAITING状态
6.TERMINATED 状态
线程结束时的状态,run()方法执行完成

wait()与notify()

它们都使用synchronized,它们的实现是基于对象,

interrupt()

interrupt()操作在线程处于BLOCKEN, RUNNING状态没有作用,只对WAITING, TIME_WAITING状态的线程有用,让它们产生异常
还可以通过isInterrupt()判断线程是否已经被调用过中断方法

stop()与interrupt()

interrupt()是相对缓和的处理方式,stop()对处于RUNNING状态的任务会导致任务直接抛出java.lang.ThreadDeath的Error,会有一定的风险。

线程优先级

Java提供了1-10个优先级,理论上数字越大优先级越高
可以通过setPriority()来设置优先级
在JVM中还有一种特殊的后台线程,可以通过setDaemon(boolean)设置是否为后台线程,它通常优先级很低,JVM的GC线程就是后台线程,后台线程有一种很重要的的特征,如果JVM进程中活着的线程只有后台线程,就要结束整个进程。

线程合并(Join)

package myList;

class ThreadTesterA implements Runnable {

    private int counter;

    @Override
    public void run() {
        while (counter <= 10) {
            System.out.print("Counter = " + counter + " ");
            counter++;
        }
        System.out.println();
    }
}

class ThreadTesterB implements Runnable {

    private int i;

    @Override
    public void run() {
        while (i <= 10) {
            System.out.print("i = " + i + " ");
            i++;
        }
        System.out.println();
    }
}

public class ThreadTester {
    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(new ThreadTesterA());
        Thread t2 = new Thread(new ThreadTesterB());
        t1.start();
        t1.join(); // wait t1 to be finished
        t2.start();
        t2.join(); // in this program, this may be removed
    }
}

//i = 0 Counter = 0 Counter = 1 i = 1 Counter = 2 i = 2 Counter = 3 i = 3 Counter = 4 Counter = 5 Counter = 6 Counter = 7 Counter = 8 Counter = 9 Counter = 10 
i = 4 i = 5 i = 6 i = 7 i = 8 i = 9 i = 10 

可以实现同步的作用

线程安全

一致性问题一般出现在多核机器上

package myList;

public class ThreadTest extends Thread{

    private boolean ready;

    private int number;

    public void run(){
        while(!ready){
            number++;
        }
        System.out.println(ready);
    }

    public void readyOn(){
        this.ready = true;
    }

    public static void main(String [] args){
        ThreadTest readThread = new ThreadTest();
        readThread.start();
        try {
            Thread.sleep(200);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        readThread.readyOn();
        System.out.println(readThread.ready);

    }
}

代码可能会不能停止,因为不同变量的修改不需要立即写回到主存,而线程读取也不需要每一次去读取数据。
解决方法:1.在循环中添加一个Thread.yield(),操作就可以让线程让步CPU,进而很可能到主存中读取最新的ready的值。2.在循环中加一条System.out语句,或者将ready变量增加一个volatile修饰符也可以达到退出的目的。

ThreadLocal

ThreadLocal可以放一个线程级别的变量,但它本身可以被多个线程共享使用,而又达到线程安全的目的,且绝对线程安全。

public final static ThreadLocal<String> RESOURCE = new ThreadLocal<String>();

RESOURCE代表一个可以存放String类型的ThreadLocal对象,任何一个线程可以并发访问这个变量,对它进行写入,读取操作,都是线程安全的

原子性和锁

synchronized
synchronized通过在对象上加锁后进入临界区达到临界区串行访问的目的
1.普通方法前面加synchronized

synchronized public void test() {}

锁住了类的对象
2. 静态方法前面加synchronized

synchronized public static void test() {}

锁住了当前类
3. 代码块加锁

synchronized(object){
    //代码
}

锁住的不是代码而是object对象

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值