线程操作系统进行资源分配的最小单元,进程之间相互独立。
CPU时间片轮转机制 并行和并发CPU调度最小单位,线程必须依赖进程存在。
多线程利与弊并行:可以同时运行的任务数
并发:单位时间内的并发量,交替执行。
线程创建利:充分利用CPU的资源、加快响应用户的时间、代码模块化,异步化,简单化。
弊:线程安全问题、性能问题、消耗资源问题
Linux 1000个线程数
Windows 2000个线程数
线程停止JDK在Thread类中注释讲过,创建线程只有2种方式。
Thread、Runnable
区别:
Thread对线程的抽象
Runnable对任务的抽象
stop废弃方法,不建议使用,会导致线程占用的资源不会正常释放。
interrupt 对线程进行中断,对线程进行通知,是否真正立即中断,不一定。
isInterrupted 判断线程是否被中断,中断后,isInterrupted()返回值为true
Thread.interrupted 判断线程是否被中断,中断后,isInterrupted()返回值为false
线程是协作式的,而不是抢占式
public class UseThread extends Thread {
public UseThread(String name) {
super(name);
}
@Override
public void run() {
Thread thread = Thread.currentThread();
System.out.println("stat>>thread name:" + thread.getName() + " interrupt flag:" + isInterrupted());
while(!isInterrupted()){
//while (!Thread.interrupted()) {
System.out.println(thread.getName() + " is running");
System.out.println("middle>>thread name:" + thread.getName() + " interrupt flag:" + isInterrupted());
}
System.out.println("end>>>thread name:" + thread.getName() + " interrupt flag:" + isInterrupted());
}
}
public static void main(String[] args) throws InterruptedException {
UseThread useThread = new UseThread("cc");
useThread.start();
Thread.sleep(100);
useThread.interrupt();
}
public class UseThread extends Thread {
public UseThread(String name) {
super(name);
}
@Override
public void run() {
Thread thread = Thread.currentThread();
System.out.println("stat>>thread name:" + thread.getName() + " interrupt flag:" + isInterrupted());
while(!isInterrupted()){
System.out.println(thread.getName() + " is running");
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
System.out.println("middle>>crash>>>>thread name:" + thread.getName() + " interrupt flag:" + isInterrupted()+ "error:"+e);
//捕获到中断异常后,需要手动再次调用interrupt()后,isInterrupted()才会返回true
interrupt();
}
System.out.println("middle>>thread name:" + thread.getName() + " interrupt flag:" + isInterrupted());
}
System.out.println("end>>>thread name:" + thread.getName() + " interrupt flag:" + isInterrupted());
}
}
理解start和run
ThreadRun threadRun=new ThreadRun();
threadRun.setName("threadRun");
//输出 thread name: main
//threadRun.run();
//输出 thread name: threadRun
threadRun.start();
线程生命周期
线程优先级yield():将线程从运行转化到可运行状态, 不会释放锁
join(): A 线程中 执行B线程.join() , 线程A挂起,B线程执行,B线程执行完毕,A线程继续执行。
守护线程默认是5,范围1~10
setPriority() 操作系统决定,不一定起作用。
线程间的共享程序后台运行,如调度 、垃圾回收等线程。 非守护线程全部停止后,守护线程也会跟着停止。
setDaemon(true)
错误的加锁和错误原因synchronized内置锁:保证在某一个时刻,只有一个线程执行
同步块、同步方法 属于对象锁
类锁:虚拟机中class对象, 类加载器生成。
类锁和对象锁,可以并行执行。
不同的对象,在不同线程执行,可以并行执行。
相同的对象,对象内有内置锁,在不同的线程执行,不会并行执行。
volatilesynchronized锁的是对象,锁的不是同一个对象,会导致错误加锁
最轻量级的同步机制,确保可见性,当某个线程对volatile修饰的变量进行修改,可以被其他线程马上看到。
场景:一个线程进行写,多个线程进行读。
public class Valatile {
private static volatile boolean ready;
private static int number;
private static class PrintThread extends Thread {
@Override
public void run() {
System.out.println("PrintThread is running......");
while (!ready) ;
System.out.println("number:" + number);
}
}
public static void main(String[] args) throws InterruptedException {
new PrintThread().start();
Thread.sleep(1000);
number = 51;
ready = true;
Thread.sleep(2000);
System.out.println("main is end");
}
}
ThreadLocal辨析
为每个线程提供变量的副本,每个线程访问之际的数据,实现线程的隔离。
public class UseThreadLocal {
private static ThreadLocal threadLocalInteger = new ThreadLocal<>();
private static ThreadLocal threadLocalString = new ThreadLocal<>();
public static void main(String[] args) throws InterruptedException {
//放在主线程对应的ThreadLocalMap中
threadLocalInteger.set(1);
//放在主线程对应的ThreadLocalMap中
threadLocalString.set("a");
//从主线程获取ThreadLocalMap,然后通过threadLocalInteger作为key取值
threadLocalInteger.get();
//从主线程获取ThreadLocalMap,然后通过threadLocalString作为key取值
threadLocalString.get();
}
}
public void set(T value) {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null)
map.set(this, value);
else
createMap(t, value);
}
public T get() {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null) {
ThreadLocalMap.Entry e = map.getEntry(this);
if (e != null) {
@SuppressWarnings("unchecked")
T result = (T)e.value;
return result;
}
}
return setInitialValue();
}
内存溢出
堆栈强引用:正常方式生成的对象。
软引用SoftRefence:发生内存溢出,软引用会被回收。
弱引用WeakReference:只要发生垃圾回收GC,弱引用就会回收。
虚引用:发生GC时,通知相关地方,当前对象要被垃圾回收
在线程执行某个方法时,方法会在线程所谓的栈上运行,当我们执行方法时,会把方法打包成栈帧。 方法内对象是存放在堆区。



