进程历史
疑问:进程和线程的区别
答:进程是资源分配的最小单位,手握操作系统给他分配的monney,是分包商
线程是CPU调度的最小单位,不持有资源,去请求进程的资源,并消耗资源
进程是抢占处理机的调度单位,拥有内存中虚拟空间
线程属于某个进程,占用该进程的地址空间
疑问:什么是资源?
答:资源信息包括程序段、数据集,所有与进程相关的资源,都被记录在PCB中。
疑问:线程拥有什么?
答:堆栈寄存器、程序计数器和TCB
Java采用单线程编程模型,程序主动创建主线程。
疑问:什么是单线程编程模型
答:不特殊指定,默认是主线程。有耗时操作,放在子线程里。
主线程往往最后执行完毕,最后死掉。
疑问:既然是单线程模型,那JVM是否是单线程模型?
答:JVM实例创建之时,有多线程,如GC、
创建线程
方式1
public class CreateThread {
public static void main(String[] args) {
Thread t1 = new Thread();
Thread t2 = new Thread() {
@Override
public void run() {
System.out.println("==========");
}
};
t1.start();
t2.start();
System.out.println(t1.getName());
System.out.println(t2.getName());
Thread t3 = new Thread("MyName");
Thread t4 = new Thread(() -> {
System.out.println("Runnable...");
});
System.out.println(t3.getName());
System.out.println(t4.getName());
Thread t5 = new Thread(() -> {
System.out.println("Runnable..." + Thread.currentThread().getName());
}, "RunnableThread");
t5.start();
}
}
方式2
public class CreateThread2 {
public static void main(String[] args) {
Thread t = new Thread() {
public void run() {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
t.start();
// System.out.println(t.getThreadGroup());
// System.out.println(Thread.currentThread().getName());
ThreadGroup threadGroup = Thread.currentThread().getThreadGroup();
// System.out.println(threadGroup.getName());
System.out.println(threadGroup.activeCount());
Thread[] threads = new Thread[threadGroup.activeCount()];
threadGroup.enumerate(threads);
Arrays.asList(threads).forEach(System.out::println);
}
}
方式3 主线程
public class CreateThread3 {
private int i = 0;
private byte[] bytes = new byte[1024];
private static int counter = 0;
//JVM will create a thread named "main"
public static void main(String[] args) {
//create a JVM stack
try {
add(0);
} catch (Error e) {
e.printStackTrace();
System.out.println(counter);
}
}
private static void add(int i) {
++counter;
add(i + 1);
}
}
方式4
public class CreateThread4 {
private static int counter = 1;
public static void main(String[] args) {
Thread t1 = new Thread(null, new Runnable() {
@Override
public void run() {
try {
add(1);
} catch (Error e) {
System.out.println(counter);
}
}
private void add(int i) {
counter++;
add(i + 1);
}
}, "Test", 1 << 24);
t1.start();
}
}
方式5
public class CreateThread5 {
private static int counter = 1;
public static void main(String[] args) {
try {
for (int i = 0; i < Integer.MAX_VALUE; i++) {
counter++;
new Thread(new Runnable() {
@Override
public void run() {
try {
add(1);
} catch (Error e) {
// System.out.println(counter);
}
}
private void add(int i) {
add(i + 1);
}
}).start();
}
} catch (Error e) {
counter++;
}
System.out.println("Total created thread nums=>" + counter);
}
}
Thread的start与run区别
start会创建新的子线程,并启动
run只是Trhead的普通方法调用,仍然在主线程执行。
Thread与Runnable区别
线程设置Daemon、优先级、ID
Daemon线程
public class DaemonThread {
public static void main(String[] args) throws InterruptedException {
Thread t = new Thread() {
@Override
public void run() {
try {
System.out.println(Thread.currentThread().getName() + " running");
Thread.sleep(100000);
System.out.println(Thread.currentThread().getName() + " done.");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}; //new
t.start();
t.setDaemon(true);
//runnable ->running| ->dead| ->blocked
Thread.sleep(5_000); //JDK1.7
System.out.println(Thread.currentThread().getName());
}
}
/**
* A<---------------------------------->B
* ->daemonThread(health check)
* */
Daemon线程2
public class DaemonThread2 {
public static void main(String[] args) {
Thread t = new Thread(() -> {
Thread innerThread = new Thread(() -> {
try {
while (true) {
System.out.println("Do some thing for health check.");
Thread.sleep(1_000);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
});
//innerThread.setDaemon(true);
innerThread.start();
try {
Thread.sleep(1_000);
System.out.println("T thread finish done.");
} catch (InterruptedException e) {
e.printStackTrace();
}
});
//t.setDaemon(true);
t.start();
}
}
线程ID、优先级
普通场景
public class ThreadSimpleAPI {
public static void main(String[] args) {
Thread t = new Thread(() -> {
Optional.of("Hello").ifPresent(System.out::println);
try {
Thread.sleep(100000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}, "t1");
t.start();
Optional.of(t.getName()).ifPresent(System.out::println);
Optional.of(t.getId()).ifPresent(System.out::println);
Optional.of(t.getPriority()).ifPresent(System.out::println);
}
}
实际场景
public class ThreadSimpleAPI2 {
public static void main(String[] args) {
Thread t1 = new Thread(() -> {
for (int i = 0; i < 1000; i++) {
Optional.of(Thread.currentThread().getName() + "-Index" + i).ifPresent(System.out::println);
}
});
t1.setPriority(Thread.MAX_PRIORITY);
Thread t2 = new Thread(() -> {
for (int i = 0; i < 1000; i++) {
Optional.of(Thread.currentThread().getName() + "-Index" + i).ifPresent(System.out::println);
}
});
t2.setPriority(Thread.NORM_PRIORITY);
Thread t3 = new Thread(() -> {
for (int i = 0; i < 1000; i++) {
Optional.of(Thread.currentThread().getName() + "-Index" + i).ifPresent(System.out::println);
}
});
t3.setPriority(Thread.MIN_PRIORITY);
t1.start();
t2.start();
t3.start();
}
}
工具jconsole
线程中断1
public class ThreadClose {
private static class Worker extends Thread {
@Override
public void run() {
while (true) {
if (Thread.interrupted())
break;
}
//-------------
//-------------
//-------------
}
}
public static void main(String[] args) {
Worker worker = new Worker();
worker.start();
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
worker.interrupt();
}
}
线程中断2
public class ThreadService {
private Thread executeThread;
private boolean finished = false;
public void execute(Runnable task) {
executeThread = new Thread() {
@Override
public void run() {
Thread runner = new Thread(task);
runner.setDaemon(true);
runner.start();
try {
runner.join();
finished = true;
} catch (InterruptedException e) {
//e.printStackTrace();
}
}
};
executeThread.start();
}
public void shutdown(long mills) {
long currentTime = System.currentTimeMillis();
while (!finished) {
if ((System.currentTimeMillis() - currentTime) >= mills) {
System.out.println("任务超时,需要结束他!");
executeThread.interrupt();
break;
}
try {
executeThread.sleep(1);
} catch (InterruptedException e) {
System.out.println("执行线程被打断!");
break;
}
}
finished = false;
}
}
JMM内存模型、线程安全
什么是Java内存模型中的happens-before
Java内存模型JMM
Java内存模型(即JavaMemoryModel,简MM)本身是一种抽象的念,
并不真实存在它描述的是一组规则或规范,通过这组规范定义了程序中各个
变量(包括实例字段,静态字段和构成数组对象的元素)的访问方式·
JMM中的主内存
-存储」ava实例对象
-声包括成员变量、类信息、常量、静态变量等
-声属于数据共享的区域,多线程并发操作时会引发线程安全问题
JMM与Java内存区域划分是不同的概念层冫欠
-jMM描述的是一组规则,围绕原子性,有序性、可见性展开
-相似点:存在共享区域和私有区域
jMM中的主内存和工作内存
主内存与工亻乍内存的存储类型以及操亻乍方式归纳
-方法里的基本数据举型本地变量将直接存储在工作内存的栈帧结构
-引用类型的本地变量:引用存储在工作内存中,实例存储在主内存
-成员变量、static变量、类信息均会被存储在主内存中
-主内存共享的方式是线程各拷贝删分数据到工作内存,操作完成
后刷新回主内存
volatile和synchronized的区别
demo实力:
volatile和synchronized的区别
1.vo丨ati|e本质是在告诉」VM当前变量在寄存器(工作内存)中的值是不确
定的,需要从主存中读取,synchronized则是锁定当前变量,只有当前
线程可以访问该变量,其他线程被阻塞住直到该线程完成变量操亻乍为止
2,vo|ati|e仅能使用在变量级别;synchronized则可以使用在变量、方法
和类级别
3.v引ati|e仅能实现变量的修改可见性,不能保证原子性而
syn(hronized则可以保证变量修改的可见性和原子性
4,vo丨ati|e不会造成线程的阻塞,syn(hronized可能会造成线程的阻塞
5.volati|e标记的变量不会被编译器优化,synchronizedfii己的变量可以
被编译器优化
synchronized和lock区别
1)Lock是一个接口,而synchronized是Java中的关键字,synchronized是内置的语言实现;
2)synchronized在发生异常时,会自动释放线程占有的锁,因此不会导致死锁现象发生;而Lock在发生异常时,如果没有主动通过unLock()去释放锁,则很可能造成死锁现象,因此使用Lock时需要在finally块中释放锁;
3)Lock可以让等待锁的线程响应中断,而synchronized却不行,使用synchronized时,等待的线程会一直等待下去,不能够响应中断;
4)通过Lock可以知道有没有成功获取锁,而synchronized却无法办到。
5)Lock可以提高多个线程进行读操作的效率。
在性能上来说,如果竞争资源不激烈,两者的性能是差不多的,而当竞争资源非常激烈时(即有大量线程同时竞争),此时Lock的性能要远远优于synchronized。所以说,在具体使用时要根据适当情况选择。
synchronized与线程安全
恰当的合理的上锁,是线程安全的关键
synchronized安全问题的主要诱因
声存在共享数据他称临界资源)
龙存在多条线程共同操作这些共享数据
解决问题的根本方法
同一时刻有且只有一个线程在操作共享数据其他线程必须等到该线
程处理完数据后再对共享数据进行操作
synchronized互斥锁(原子性)的特性
互斥性·即在同一时间只允许一个线程持有某个对象锁,通过这种特性
来实现多线程的协调机制,这样在同一时间只有一个线不寸需要同步的
代码块(复合操作)进行访问。互斥性也称为操作的原子性。
可见性:必须确保在锁被释放之前,对共享变量所做的修改,对于随后
获得该锁的另一个线程是可见的(即在获得锁时应获得最新共享变量的
值),否贝刂另一个线程可能是在本地缓存的某个副本上继续操作,从而引起不一致。
synchronized锁的不是代码,锁的都是对象
synchronized
根据获取的锁的分类·获取对象锁和获取类锁
获取对象锁的两种用法
1.同步代码块(synchronized(this),synchronized(类实例对
象)),锁是小括号0中的实例对象。
2,同步非静态方法(synchronizedmethod)锁是当前对象的实
例对象。
疑问:waite与sleep的区别
疑问:线程的生命周期