又到了多线程高并发的一天。
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下载、安装与使用教程