知识点一:
多线程中锁的认识:(synchronized)
1.锁是什么?
锁是一个独一无二标识
2.锁跟对象的关系
对象在内存中是独一无二的,所有一般把对象当成锁,锁信息可以存在对象头中
3.锁的作用范围
锁一般作用于方法或者代码块上;一把锁可以用在不同的方法上
//例1
Class A{
private B b=new B("张三");
public static void start(){
new Thread(()->thread1(),"Thread1").start();
new Thread(()->thread2(),"Thread2").start();
}
//线程Thread1中的方法
synchronized thread1(){
//睡5秒
Thread.sleep(5000)
//获取b对象中的name属性
b.getName().sout
}
//线程Thread2中的方法
thread2(){
b.setName("李四")
}
}
//例1结果分析:
therad1中的synchronized是以A类对象作为锁,thread2方法中没有上锁;所以不存在锁资源竞争,输出结果为:李四
//例2
Class A{
private B b=new B("张三");
public static void start(){
new Thread(()->thread1(),"Thread1").start();
new Thread(()->thread2(),"Thread2").start();
}
//线程Thread1中的方法
synchronized thread1(){
//睡5秒
Thread.sleep(5000)
//获取b对象中的name属性
b.getName().sout
}
//线程Thread2中的方法
thread2(){
synchronized(b){
b.setName("李四")
}
}
}
//例2结果分析
therad1中的synchronized是以A类对象作为锁,thread2方法中以对象b作为锁;所以也不存在锁资源竞争,输出结果为:李四
知识点二:
synchroniced锁在对象间是否具备传递性?
Class A{
private B b;
public synchronized void test(){
}
public void test2(){
synchronized(b){
}
}
}
//分析:
test的锁对象为a,test2的锁对象为b,a中有属性b,当不同线程同时调用test()和test2()是否存在竞争关系呢?
对象a和对象b是不同的对象,所以两个方法使用的锁不一样,因此不存在竞争关系,所以不存在传递性。
知识点三:
两个线程同时对相同的资源进行更改,其中一个线程调用sleep()那么,当前线程的锁资源会不会释放
Class A{
private B b=new B("张三");
public static void start(){
new Thread(()->thread1(),"Thread1").start();
Thread.sleep(100);//先让线程Thread1抢到资源
new Thread(()->thread2(),"Thread2").start();
new Thread(()->thread3(),"Thread3").start();//实时查看b的值
}
//线程Thread1中的方法
synchronized thread1(){
b.setName("李四");
//睡5秒
Thread.sleep(1000000000000000000000)
//获取b对象中的name属性
System.out.println(b.getName());
}
//线程Thread2中的方法
synchronized thread2(){
b.setName("王五");
System.out.println(b.getName());
}
//线程Thread3中的方法
synchronized thread3(){
while(true){
System.out.println(b.getName());
}
}
}
//获取的结果永远是李四:
synchronized中sleep不会释放资源,wait会释放资源。
知识点四:
thread.sleep(1000)究竟是哪个线程在sleep
class A{
public static void main(){
Thread thread1=new Thread1();
Thread thread2=new Thread2();
thread1.start();
thread2.start();
thread1.sleep(5000);
thread2.sleep(5000);
System.out.println("end");
}
}
Class Thread1 extends Thread{
public void run(){
super.run();
for(int i=0;i<100000;i++){System.out.println(i) }
}
}
Class Thread2 extends Thread{
public void run(){
super.run();
for(int i=0;i<100000;i++){System.out.println(i) }
}
}
//分析
在main方法中,主线程main启动了两个线程thread1和thread2,thread1和thread2调用sleep()睡5秒,其实在运行的过程中由于在主线程的方法中调用了sleep所以sleep作用在主线程。主线程睡了10000秒;
//结论
sleep()在哪个线程被调用,就作用于哪个线程,跟线程对象无关
知识点五:
1.interrupt()和isInterrupted()和interrupted()的用法
interrupt()给线程加入一个中断标记,并不会向stop()一样直接终止当前线程
isInterrupted();判断当前线程是否有interrupt标记,有的话返回true,没有返回false
interrupted();跟isInterrupted()用法一样,封装了isInterrupted();
2.如果一个线程在sleep,此时给它加一个终止标记,会直接抛出interruptedException异常,并且此线程不能被标记为interrupt
//例1:结果从1输出到100000
Class A{
public static void main(){
Thread thread1=new Thread(()->{
for(int i=0;i<100000:i++){
System.out.println(i);
}
},"thread1");
//启动线程1
thread1.start();
//主线线程睡3豪秒
Thread.sleep(3)
//给线程thread1加一个终止的标记
thread1.interrupt();
}
}
//例2:结果从1输出到198
Class A{
public static void main(){
Thread thread1=new Thread(()->{
for(int i=0;i<100000:i++){
//判断当前线程thread1是否有终止标记
if(Thread.interrupted()){break;}
System.out.println(i);
}
},"thread1");
//启动线程1
thread1.start();
//主线线程睡3豪秒
Thread.sleep(3)
//给线程thread1加一个终止的标记
thread1.interrupt();
}
}
//例3
Class A{
public static void main(){
Thread thread1=new Thread(()->{
try{
System.out.println("thread1 start")
Thread.sleep(2000000);
System.out.println("thread1 end")
}catch(InterruptedException e){
System.out.println("thread1 在沉睡时被加interrupt标记");
System.out.println(Thread.interrupted());//查看当前thread1是否被标记上interrupt
}
},"thread1");
//启动线程1
thread1.start();
//主线线程睡3豪秒
Thread.sleep(3)
//给线程thread1加一个终止的标记
thread1.interrupt();
System.out.println("main end")
}
}
//输出结果为:
thread1 start
main end
thread1 在沉睡时被加interrupt标记
false
知识点六:
线程的的权重:1-10,默认为5权重越搞cpu资源分配越多。
Class A{
public static void main(){
//定义线程1
Thread thread1 = new Thread(()->{
int count=0;
while (true){
count++;
if(Thread.interrupted()){
System.out.println(Thread.currentThread().getName()+"#"+Thread.currentThread().getPriority()+"#"+count);
break;
}
}
},"thread1");
//定义线程2
Thread thread2 = new Thread(()->{
int count=0;
while (true){
count++;
if(Thread.interrupted()){
System.out.println(Thread.currentThread().getName()+"#"+Thread.currentThread().getPriority()+"#"+count);
break;
}
}
},"thread2");
//设置权重
thread1.setPriority(Thread.NORM_PRIORITY+3);
thread2.setPriority(Thread.NORM_PRIORITY-3);
thread2.start();
thread1.start();
Thread.sleep(5000);
thread2.interrupt();
thread1.interrupt();
}
}
//输出结果:
thread1#8#839523159
thread2#2#820685026
知识点七:
守护线程daemon--当没有其他非守护线程运行时,守护线程就会自动终止
Class A{
//定义一个thread1
Thread thread1=new Thread(()->{
for(int i=0;i<20;i++){
Thread.sleep(1000);
System.out.println(i);
}
},"thread1");
//将thread1设置为守护线程
thread1.setDaemon(true);
thread1.start();
//主线程睡5秒结束
Thread.sleep(5000);
System.out.println("主线程mian结束啦");
}
//打印结果
0
1
2
3
4
主线程mian结束啦