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

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