线程安全问题

线程安全问题

public class TestSafy {
    private static String[] arr=new String[5];
    private static int  index=0;

    public static void main(String[] args) throws Exception {
        //创建一个任务放入hello
        Runnable tast01=new Runnable() { //匿名内部类
            @Override
            public void run() {
                if(arr[index]==null){ //时间到了
                    arr[index]="hello";
                    index++;
                }
            }
        };

        Runnable tast02=new Runnable() { //匿名内部类
            @Override
            public void run() {
                if(arr[index]==null){
                    arr[index]="world";//时间到了
                    index++;
                }
            }
        };

        Thread t1=new Thread(tast01,"线程A");
        Thread t2=new Thread(tast02,"线程B");
        t1.start();
        t2.start();

        t1.join();
        t2.join();

        System.out.println(Arrays.toString(arr)); //属于main


    }
}

解决线程安全问题----加锁

(1)synchronized----自动锁

public class TestSafy {
    private static String[] arr=new String[5];
    private static int  index=0;

    public static void main(String[] args) throws Exception {
        //创建一个任务放入hello
        Runnable tast01=new Runnable() { //匿名内部类
            @Override
            public void run() {
                synchronized (arr) { //()锁资源-----共享资源作为锁资源.只要使用的是同一把锁资源就可以上锁成功。
                    if (arr[index] == null) { //时间到了
                        arr[index] = "hello";
                        index++;
                    }
                }
            }
        };
        Runnable tast02=new Runnable() { //匿名内部类
            @Override
            public void run() {
                synchronized (arr) {
                    if (arr[index] == null) {
                        arr[index] = "world";//时间到了
                        index++;
                    }
                }
            }
        };

        Thread t1=new Thread(tast01,"线程A");
        Thread t2=new Thread(tast02,"线程B");
        t1.start();
        t2.start();

        t1.join();
        t2.join();

        System.out.println(Arrays.toString(arr)); //属于main


    }
}
public class TestTicket {
    public static void main(String[] args) {
         Ticket task=new Ticket();//任务对象

         Thread t1=new Thread(task,"窗口A");
         Thread t2=new Thread(task,"窗口B");
         Thread t3=new Thread(task,"窗口C");
         Thread t4=new Thread(task,"窗口D");

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

class Ticket implements Runnable {

    private Integer ticket = 100;
    private Object o=new Object(); //新建一个Object做为锁资源
    @Override
    public void run() {
        while (true) {
            synchronized (this) { //()要的是一个对象! tiket它是一个int类型
                if (ticket <= 0) {
                    break;
                }
                ticket--;
                System.out.println(Thread.currentThread().getName() + "卖了一张,剩余:" + ticket + "张");
            }
        }
    }
}

(2)lock------手动锁。

public class TestSafy {
    private static String[] arr=new String[5];
    private static int  index=0;
    public static void main(String[] args) throws Exception {
        final Lock lock=new ReentrantLock();//重入锁:可以多次加锁。 创建一个手动锁对象
        //创建一个任务放入hello
        Runnable tast01=new Runnable() { //匿名内部类
            @Override
            public void run() {
                try {
                    lock.lock();//上锁
                    if (arr[index] == null) { //时间到了
                        arr[index] = "hello";
                        index++;
                    }
                }finally {  //finally有没有异常都会执行
                   lock.unlock();//解锁
                }
            }
        };
        Runnable tast02=new Runnable() { //匿名内部类
            @Override
            public void run() {
                try {
                    lock.lock();
                    if (arr[index] == null) {
                        arr[index] = "world";//时间到了
                        index++;
                    }
                }finally {
                    lock.unlock();
                }
            }
        };

        Thread t1=new Thread(tast01,"线程A");
        Thread t2=new Thread(tast02,"线程B");
        t1.start();
        t2.start();

        t1.join();
        t2.join();

        System.out.println(Arrays.toString(arr)); //属于main


    }
}
public class TestTicket {
    public static void main(String[] args) {
         Ticket task=new Ticket();//任务对象

         Thread t1=new Thread(task,"窗口A");
         Thread t2=new Thread(task,"窗口B");
         Thread t3=new Thread(task,"窗口C");
         Thread t4=new Thread(task,"窗口D");

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

class Ticket implements Runnable {
    private Lock lock=new ReentrantLock();
    private Integer ticket = 100;
    private Object o=new Object(); //新建一个Object做为锁资源
    @Override
    public void run() {
        while (true) {
            try{
                lock.lock();
                if (ticket <= 0) {
                    break;
                }
                ticket--;
                System.out.println(Thread.currentThread().getName() + "卖了一张,剩余:" + ticket + "张");
            }finally {
                lock.unlock();
            }
        }
    }
}

HashMap和HashTable的区别?

HashMap:允许key和value为null,hashmap线程不安全,但是效率高。
HashTable:不允许key和value为null,它线程安全,效率低。

HashMap的底层如何实现?

1、 数组+链表+红黑二叉树。 hashMap存放调用的是put(key,value),根据key的hash值进行判断是否有相同哈希值的元素在数组中,如果没有则存入数组中,如果存在相同哈希值的元素,则认为哈希冲突,则比较他们的equals是否相同,如果相同,则认为是同一个元素,则替换原来key对应的value值。 如果不同,则存入链表,如果哈希冲突的元素过多(8),则存入红黑二叉树。

ArrayList和LinkedList的区别!

1. ArrayList:底层是数组结构,是一块连续的内存空间,适合查询操作,不是插入和删除操作,因为插入和删除,牵涉到数据的迁移。
2. LinkedList:底层是链表结构,适合插入和插入操作,不适合查找操作。

String,StringBuffer和StringBuilder的区别

1. String底层使用final修饰。其值不可改变,每次改变重新生成引用地址。
2. StringBuffer和StringBuilder其值可以改变,使用append进行追加。 
3. StringBuffer线程安全,但是效率低,建议多线程下使用。
4. StringBuilder线程不安全,但是效率高,建议单线程下使用。

死锁以及如何避免死锁。

线程安全问题

 线程安全问题

十秒后自动解锁

上一篇:多线程实现方式


下一篇:尚硅谷Java入门笔记 - P406 ~ P446