zoukankan      html  css  js  c++  java
  • 并发的第一天

    又到了多线程高并发的一天。

    hr问题:

    • sleep与wait的区别是什么?
    • volatile如何保证线程可见性?
    • Callable与Runnable的区别?

    来个小例子吧!

    1.首先,肯定是经典问题,多线程下的单例模式

    		private SingletonTest() {}
    		// 主内存对线程是不可见的,添加 volatile 关键字之后,主内存对线程可见。
    		private volatile static SingletonTest test = null;
    	
    		public static SingletonTest getSingletonTest() {
    	
    			if (test == null) {
    				// 创建实例之前可能会有一些准备性的耗时工作
    				try {
    					Thread.sleep(300);
    					synchronized (SingletonTest.class) {
    						if (test == null) {
    							test = new SingletonTest();
    						}
    					}
    				} catch (InterruptedException e) {
    					e.printStackTrace();
    				}
    			}
    	
    			return test;
    		}
    

    题目2:

    用多线程交替打印出a1-b2-c3-d4-e5-f6-g7····z26

    这就是所谓的线程调度,啦啦

    package com.m.thread;
    
    import java.util.Arrays;
    
    public class TestA1B2 {
    
        static Object object = new Object();
    
        public static void main(String[] args) {
    //        Object object = new Object();
            //首先准备材料
            char[] chars = "abcdefghijklmnopqrstuvwxyz".toCharArray();
            int [] number = new int[26];
    
            System.out.println(chars.length);   //26
    
            for (int i = 0; i < 26 ; i++) {
                number[i] = i+1;
            }
    
            System.out.println(Arrays.toString(number));
    
    
            new Thread(()->{
                synchronized (object){
                    for (int i = 0; i < 26; i++) {
                        System.out.print(chars[i]);
                        test();
                    }
                    object.notify();
                }
            }).start();
    
    
            new Thread(()->{
                synchronized (object){
                    for (int i = 0; i < 26; i++) {
                        System.out.print(number[i]);
                        test();
                    }
                }
            }).start();
    
    
        }
    
        public static void test(){
            try {
                Thread.sleep(500);
                object.notify();
                object.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    
    

    0.java本身是无法开启线程的,java只能通过调用本地方法start0(),通过C++编写的动态函数库去操作硬件。

     public synchronized void start() {
    
            group.add(this);
    
            boolean started = false;
            try {
                start0();
                started = true;
            } finally {
                try {
                    if (!started) {
                        group.threadStartFailed(this);
                    }
                } catch (Throwable ignore) {
                }
            }
        }
    
        private native void start0();
    

    1.死锁问题

    package com.m.thread;
    
    
    public class Test1 implements Runnable {
        public int num;
    
        private static Object object = new Object();
        private static Object object1 = new Object();
        @Override
        public void run() {
    
            if(num == 1){
                synchronized (object){
                    System.out.println(num+"拿到了对象object");
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    synchronized (object1){
                        System.out.println(num+"拿到了对象object1");
                    }
                }
            }
    
            if(num == 2) {
                synchronized (object1){
                    System.out.println(num+"拿到了对象object1");
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    synchronized (object){
                        System.out.println(num+"拿到了对象object");
                    }
                }
            }
    
        }
    }
    
    
    package com.m.thread;
    
    public class Test2 {
    
        public static void main(String[] args) {
            Test1 test1 = new Test1();
            test1.num = 1;
            Test1 test11 = new Test1();
            test11.num = 2;
    
            new Thread(test1).start();
            //预防死锁
    //        try {
    //            Thread.sleep(2000);
    //        } catch (InterruptedException e) {
    //            e.printStackTrace();
    //        }
            new Thread(test11).start();
        }
    }
    
    

    synchronized导致的死锁-DeadLock-02

    package com.m.test;
    
    
    public class Class01 {
    	static Thread t1 = null, t2 = null;
    
    	public static void main(String[] args) {
    		final Object o = new Object();
    		final Object o2 = new Object();
    		char[] c1 = "12345".toCharArray();
    		char[] c2 = "abcde".toCharArray();
    
    		t1 = new Thread(() -> {
    			synchronized (o) {
    				for (int i = 0; i < c1.length; i++) {
    					System.out.print(c1[i]);
    					try {
    						Thread.sleep(1000);
    					} catch (InterruptedException e1) {
    						// TODO Auto-generated catch block
    						e1.printStackTrace();
    					}
    					try {
    						t2.join();
    					} catch (InterruptedException e) {
    						e.printStackTrace();
    					}
    				}
    			}
    
    		}, "t1");
    
    		t2 = new Thread(() -> {
    			synchronized (o2) {
    				for (int i = 0; i < c2.length; i++) {
    					System.out.print(c2[i]);
    					try {
    						t1.join();
    					} catch (InterruptedException e) {
    						e.printStackTrace();
    					}
    				}
    			}
    		}, "t2");
    
    		t1.start();
    		t2.start();
    	}
    }
    

    2.实现接口Callable
    创建线程有三种方式

    • Thread
    • Runnable
    • Callable

    Callable与Runnable的区别?

    1.Callable在线程start()执行完,可以返回一个值

    2.Callable的call()方法可以抛异常。

    package com.m.thread;
    
    
    import java.util.concurrent.Callable;
    
    public class Test1 implements Callable<String> {
    
        @Override
        public String call() throws Exception {
            return "Callable";
        }
    
    }
    
    
    package com.m.thread;
    
    import java.util.concurrent.ExecutionException;
    import java.util.concurrent.FutureTask;
    
    public class Test2 {
    
        public static void main(String[] args) {
            Test1 test1 = new Test1();
            FutureTask<String> futureTask = new FutureTask<String>(test1);
    
            Thread thread = new Thread(futureTask);
    
            thread.start();
    
            try {
                System.out.println(futureTask.get());
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (ExecutionException e) {
                e.printStackTrace();
            }
        }
    }
    
    

    3.sleep 是Thread类的静态本地方法,可以通过类调用,也可以通过对象调用,
    方法定义抛出 InterruptedException,InterruptedException 继承 Exception,

    在类的外部调用 sleep 方法。

    MyThread2 thread = new MyThread2();
    try {
      thread.sleep(5000);
    } catch (InterruptedException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
    thread.start();
    

    main线程休眠

    package com.m.thread;
    
    
    public class Test2 {
    
        public static void main(String[] args) {
            try {
                Thread.currentThread().sleep(5000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            for (int i = 0; i <10 ; i++) {
                System.out.println(i);
            }
        }
    
    }
    
    

    4.只用volatile来保持变量的线程同步是不行的。

    package com.m.thread;
    
    public class Test1 implements Runnable{
        private volatile static int num;
    
        @Override
        public void run() {
           num++;
    
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
    
            System.out.println(Thread.currentThread().getName()+"是当前第"+num+"位访客");
        }
    }
    
    
    package com.m.thread;
    
    public class Test2 {
    
        public static void main(String[] args) {
            Test1 test1 = new Test1();
    
            Thread thread = new Thread(test1,"张三");
            Thread thread1 = new Thread(test1,"李四");
    
            thread.start();
            thread1.start();
        }
    }
    
    

    ReentrantLock可重人锁

    package com.m.thread;
    
    import java.util.concurrent.locks.Lock;
    import java.util.concurrent.locks.ReentrantLock;
    
    public class Test1 implements Runnable {
        private static int num;
        private Lock lock = new ReentrantLock();
    
        @Override
        public void run() {
    
            try {
    
                lock.lock();
                lock.lock();
                num++;
                Thread.sleep(1000);
                System.out.println(Thread.currentThread().getName() + "是当前第" + num + "位访客");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }finally {
                lock.unlock();
                lock.unlock();
            }
    
        }
    }
    
    

    5.interrupt 是一个实例方法,当一个线程对象处于不同的状态时,中断机制也是不同的。

    package com.m.thread;
    
    
    public class Test2 {
    
        public static void main(String[] args) {
    
            Thread thread = new Thread();
            
            System.out.println(thread.getState());      //NEW
            System.out.println(thread.getPriority());   //5
    
            thread.interrupt();
    
            System.out.println(thread.isInterrupted()); //false
            //true表示清除了标志位,当前线程对象已经中断,false表示没有清除标志位,当前线程对象没有中断。
        }
    }
    
    
    package com.m.thread;
    
    
    public class Test2 {
    
        public static void main(String[] args) {
    
            Thread thread = new Thread();
            thread.start();
            System.out.println(thread.getState());      //RUNNABLE
            System.out.println(thread.getPriority());   //5
            
            thread.interrupt();
    
            System.out.println(thread.isInterrupted()); //true
        }
    }
    
    

    6.join方法的重载

    public final void join() throws InterruptedException {
            join(0);
    }
    
    public final synchronized void join(long millis)
        throws InterruptedException {
        long base = System.currentTimeMillis();
        long now = 0;
    
        if (millis < 0) {
            throw new IllegalArgumentException("timeout value is negative");
        }
    
        if (millis == 0) {
            while (isAlive()) {
                wait(0);
            }
        } else {
            while (isAlive()) {
                long delay = millis - now;
                if (delay <= 0) {
                    break;
                }
                wait(delay);
                now = System.currentTimeMillis() - base;
            }
        }
        }
    

    final来修饰类 方法 属性都表示其值不可变,也就是说类不可继承,方法不可重写,属性不可覆盖。

    7.yield

    public static native void yield();
    

    8.interrupt

    
    
    public class Class03 {
    	public static void main(String[] args) {
    		Thread thread = new Thread(new Runnable() {
    
    			@Override
    			public void run() {
    				for (int i = 0; i < 10; i++) {
    					System.out.println(i + "---main");
    				}
    			}
    
    		});
    		thread.start();
    		System.out.println(thread.getState());
    		thread.interrupt();
    		System.out.println(thread.isInterrupted());
    		System.out.println(thread.getState());
    	}
    }
    
    /**
            RUNNABLE
            true	
            0---main
            BLOCKED
            
            当一个线程对象处于不同的状态时,中断机制也是不同的。
    */
    
    

    java8新特性

    10.注解,新旧对比,新旧交替。

    5.lambda的作用域

    2.lambda表达式

    1.接口的默认方法

    Maven WEB 创建很慢解决方案:

    https://www.cnblogs.com/yachao1120/p/10847889.html

    Python idle下载、安装与使用教程

    https://blog.csdn.net/yatum_2014/article/details/81291666

  • 相关阅读:
    常见排序算法(上)
    二.CSS的伪类
    ASP.NET_编码模型
    一.CSS工作原理
    如何拦截来电,并检测到某些特定号码时自动挂断电话
    如何获取短信内容
    Android导入项目时出现红色感叹号
    如何接收广播;如何发送广播
    设置Activity显示和关闭时的动画效果
    将Activity设置成半透明的对话框
  • 原文地址:https://www.cnblogs.com/k-class/p/13703767.html
Copyright © 2011-2022 走看看