多线程基础知识笔记

创建线程的三种方式

要启动线程必须重写run方法
1.继承Thread类

public class serverThread extends Thread{
       public String str;
       //方法的重载
       public serverThread(String str){
       this.str=str;
      public void run(){
      }
}

2.实现Runnable接口。

public class ClientThread implements Runnable{
public void run(){
}
}

3.匿名类

public class NoThread implements Runnable{
Thread t1=new Thread(){
public void run(){
}
};
t1.start();
或者
new Thread(){
public void run(){

}
}.start();
}

线程的常用方法

共同点:必须使用try抓住InterruputedException异常
1.sleep(long mills):使线程睡眠给定毫秒的时间。
2.join()😕/使线程加入到main线程中来,只有线程运行结束,才会继续往下走
3.setPriority(int Priority):设置线程优先级,当线程处于竞争关系的时候,优先级高的线程会有更大的几率获得CPU资源,线程最大优先级可用Thread.MAX_PRIORITY表示 ,不过在使用了join()方法之后,setPriority()方法无效。例子:
Thread t1;t1.setPriority(Thread.MAX_PRIORITY);
4.yield():临时暂停线程,使其他线程可以参与工作

public class TestThread {
     static class Hero{
    	 String name;
    	 int hp;
    	 public void heroisattacked() {
    		 this.hp--;
    	 }
    	 public void herocured() {
    		 this.hp++;
    	 }
     }
     public static void main(String args[]) {
    	 Hero h=new Hero();
    	 h.name="凯";
    	 h.hp=1000;
     Thread t1=new Thread() {
    		 public void run() {
    			 for(int i=0;i<100;i++) {
    				 
    					//1.使用sleep方法睡眠100毫秒	 
                     try{
                    	 Thread.sleep(100);
                    	 4.暂停线程
                    	 Thread.yield();
                     }catch(InterruptedException e) {
                    	 e.printStackTrace();
                     }


    			 h.heroisattacked();
    			 System.out.printf("英雄%s减血后剩下%d血%n",h.name,h.hp);
    			 }
    		 }
    	 };    	 
    	 t1.start();


    	  //2.使用Join()方法,使t1线程加入到main线程中来,只有线程运行结束,才会继续往下走,注意join()必须在strat()之后使用。
    	 /*try {
    		 t1.join();
    	 }catch(InterruptedException e) {
    		 e.printStackTrace();
    	 }*/

    	 Thread t1=new Thread() {
    		 public void run() {
    			 for(int i=0;i<100;i++) {
    				  try{
    	                	 Thread.sleep(100);
    	                 }catch(InterruptedException e) {
    	                	 e.printStackTrace();
    	                 }
    			 h.herocured();
    			 System.out.printf("英雄%s加血后剩下%d血%n", h.name,h.hp);
    			 }
    		 }
    	 };
    	t2.start();
    	t1.setPriority(5);
        t2.setPriority(5);
     }
}

线程的同步

synchronized(Object someObject)方法:多个线程占有someObject对象后再使用线程方法,如果其他线程试图占有对象,就会等待,只有在线程方法结束后,才会释放someObject对象。解决了多个线程修改同一个值而产生的脏数据问题。

                          Object someObject=new Object();
                          synchronized(someObject) {
    					//1.使用sleep方法睡眠100毫秒	 
                     try{
                    	 Thread.sleep(100);
                    	
                     }catch(InterruptedException e) {
                    	 e.printStackTrace();
                     }
                     
    			 h.heroisattacked();
    			 }
                          synchronized(someObject) {
    				  try{
    	                	 Thread.sleep(100);
    	                 }catch(InterruptedException e) {
    	                	 e.printStackTrace();
    	                 }
    				 
    			 h.herocured();
    				 }

在方法内部加上synchronized修饰,可以达到在run方法内部使用synchronized占有对象同样的效果。

Public synchronized void heroisattcked(){
           this.hp--;
}
Public synchronized void herocured(){
           this.hp++;
}

线程的交互

如果对象血量过少,或者减血线程一直优先加血线程循环启动,那么对象的血量就会被减为负数,这显然是不利于人机交互的。所以,需要使用线程交互相关的方法来进行多线程交互。
相关方法:this.wait(),this.notify()
可以在线程安全的减血方法中加上if语句,当hp==1时,使用this.wait()让减血线程等待,并临时释放占有。这样加血线程就有机会占有对象,加血后再使用this.notify()的话就可以让在等待的减血线程苏醒过来。

Public synchronized void heroisattcked(){
if(hp==1) {
                 try {
    		   		 this.wait();
    		   	 }catch(InterruptedException e) {
    		   		 e.printStackTrace();
    		   	 }
    	 }
           this.hp--;
           
}
Public synchronized void herocured(){
           this.hp++;
           this.notify();
}

不过以上代码仅适用于减血线程和加血线程数量相等的情况。

当减血线程多于加血线程,就需要修改启动this,wait()的条件为while(hp<=1)。加血线程多于减血线程时同理

//两个减血线程,一个加血线程(省略代码)
 Thread t1=new Thread() {
    		 public void run() {
    			while(true) {
    				 
    					//1.使用sleep方法睡眠100毫秒	 
                     try{
                    	 Thread.sleep(100);
                  
                     }catch(InterruptedException e) {
                    	 e.printStackTrace();
                     }
                     
    			 h.heroisattacked();
    		
    				 
    			System.out.printf("英雄%s减血后剩下%d血%n", h.name,h.hp);
    			 
    			 }
    		 }
    	 };
    	 t1.setPriority(5);
  
    	 t1.start();
    	 Thread t3=new Thread() {
    		 public void run() {
    			while(true) {
    				 
    					//1.使用sleep方法睡眠100毫秒	 
                     try{
                    	 Thread.sleep(100);
                  
                     }catch(InterruptedException e) {
                    	 e.printStackTrace();
                     }
                     
    			 h.heroisattacked();
    	
    				 
    			System.out.printf("英雄%s减血后剩下%d血%n", h.name,h.hp);
    			 
    			 }
    		 }
    	 };
Public synchronized void heroisattcked(){
while(hp<=1) {
                 try {
    		   		 this.wait();
    		   	 }catch(InterruptedException e) {
    		   		 e.printStackTrace();
    		   	 }
    	 }
           this.hp--;
           
}

多线程的Lock方法

synchronized与Lock的区别

当一个线程运行了带有synchronized的方法,该线程会一直占有锁,待线程执行完毕才会释放锁,其他线程只能一直等待。试想:如果线程因为某些原因受到阻塞,无法释放锁的话,其他线程就只能一直等待,这会相当影响线程执行的效率。而Lock就能解决这个问题,Lock可以使用自带方法判断是否获取到锁(可以指定尝试获取锁的时间),亦能手动释放锁,这样就能解决线程一直等待的问题。

package socket;
import java.util.concurrent.locks.*;//导入Lock相关的打包类
import java.util.concurrent.TimeUnit;
public class TestThread {
     static class Hero{
    	 String name;
    	 int hp;
    	 public  void heroisattacked() {    		
    	    	   hp--;
    	 }
    	 public  void herocured() {
    		 hp++;
    		
    	 }
     }
  
     public static void main(String args[]) {
    	 Hero h=new Hero();
    	 h.name="凯";
    	 h.hp=100;
     
    	 //1.创建新锁,注意新锁lock相对于使用锁的同一批线程必须是同一个变量
    	 Lock lock=new ReentrantLock();
    	
    	 Thread t1=new Thread() {
    		
    		 public void run() {
    			 //2.将锁的开与关返回布尔值,避免重复关锁或者开锁而引起的程序错误
    			 boolean locked=false;
    			
    				 while(true) {
    				
    				
                     try{
                    	 //3.truLock方法返回的为布尔值,获取到锁返回真,否则返回假
                    	   locked=lock.tryLock(1,TimeUnit.SECONDS);
                    	 if(locked) {
                    		 //与使用synchronized时的交互方法类似,避免血量减为负数
                    	 if(h.hp<=0) {
                    		 lock.unlock();
                    		 locked=false;
                    	 }
                    
                    	 Thread.sleep(100);
                    
                    		h.heroisattacked();
                    		 System.out.printf("英雄%s减血后剩下%d血%n", h.name,h.hp);
                    		
                        	
                    	 }
                    	 
                     }catch(InterruptedException e) {
                    	 e.printStackTrace();
                     }finally{//4.注意try里获取到的锁,要使用finally关闭
                    	 if(locked) 
                    	 lock.unlock();
                     }
                    
    		
    
    				 
    			
    			 
    			 
    			}
    		 }
    	 };
    	 t1.setPriority(5);
  
    	 t1.start();
    	
    	 Thread t3=new Thread() {
     		
    		 public void run() {
    			 boolean locked=false;
    				 while(true) {
    				
    				
    					//1.使用sleep方法睡眠100毫秒	 
                     try{
                    	   locked=lock.tryLock(1,TimeUnit.SECONDS);
                    	 if(locked) {
                    	 if(h.hp<=0) {
                    		 lock.unlock();
                    		 locked=false;
                    	 }
                    
                    	 Thread.sleep(100);
                    
                    		h.heroisattacked();	
                    	    System.out.printf("英雄%s减血后剩下%d血%n", h.name,h.hp);
                    		
                        	
                    	 }
                    	 
                     }catch(InterruptedException e) {
                    	 e.printStackTrace();
                     }finally{
                    	 if(locked) 
                    	 lock.unlock();
                     }
                 
    		
    
    				 
    			
    			 
    			 
    			}
    		 }
    	 };
    	 t3.setPriority(5);
  
    	 t3.start();
    	 Thread t2=new Thread() {
    		 public void run() {
    			 boolean locked=false;
    	    			while(true) {
    	    			
    	    					//1.使用sleep方法睡眠100毫秒	 
    	                     try{
    	                    	 locked=lock.tryLock(1,TimeUnit.SECONDS);
    	                    	  if(h.hp>=100) {
    	                        	  lock.unlock();
    	                        	  locked=false;
    	                          }
    	                    	 Thread.sleep(100);
    	                        
    	                    	 h.herocured(); 
    	                    	  System.out.printf("英雄%s加血后剩下%d血%n", h.name,h.hp);  
    	                    	 
    	                     }catch(InterruptedException e) {
    	                    	 e.printStackTrace();
    	                     }finally {
    	                    	 if(locked) 
    	                    	 lock.unlock();
    	                     }
    	                   
    			                  
    			
    				 
    			  }
    		 }
    	 };
    	 t2.setPriority(5);
    	 t2.start();
     }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值