Java1-多线程编程(进程、实现、状态、操作方法、同步与死锁)

1、进程与线程

(1)进程:同一时间段只允许一个程序运行 。多进程允许同一时间段多个程序运行,但是同一时间点只能执行一个。

(2)线程:在进程之上划分的更小单元。线程依赖于进程支持,没有进程,线程不存在。线程启动速度远快于进程,并发处理时性能远高于进程。

2、实现多线程

(1)继承Thread类实现多线程

package xiancheng;

public class MyThread extends Thread{

	@Override
    public void run(){
        //多线程执行的功能都需要在run方法中定义
        //但是不能直接调用,启动多线程需要start()方法
        for(int i= 0;i<10;i++){
            System.out.println(i);
        }
    } 
    
    public static void main(String args[]) {
    	new MyThread().start();
    	new MyThread().start();
    }
}

  • 多线程执行的功能都需要在run方法中定义;
  • 但是不能直接调用,启动多线程需要start()方法;
  • 多教程交替执行,执行顺序不可控,虽然调用start方法,但是执行仍是run方法;
    每一个线程只允许启动一次,否则会抛出异常;如下:
    MyThread myThread = new MyThread() ;
	myThread .start();
    myThread .start();

(2)实现Runnable接口
该方式没有提供start启动方法,需要通过Thread 类启动(优先考虑)。

class xc implements Runnable{

	@Override
    public void run(){		
        //多线程执行的功能都需要在run方法中定义
        //但是不能直接调用,启动多线程需要start()方法
        for(int i= 0;i<10;i++){
            System.out.println(i);
        }
    } 
}


public class MyThread {
    
    public static void main(String args[]) {
    	Thread thread = new Thread(new xc());
    	thread.start();
    }
}

(3)实现Callable接口
Runnable接口无法获取返回值,Callable可以设置一个泛型,泛型类型为返回数据类型;
在这里插入图片描述

class xc implements Callable<String>{

	@Override
	public String call() throws Exception {
		for(int x = 0; x<10; x++) {
			System.out.print(x);
		}
		return "执行完毕";
	}

}

public class MyThread {
    
    public static void main(String args[]) throws InterruptedException, ExecutionException {
    	FutureTask<String> task = new FutureTask(new xc());
    	new Thread(task).start();
    	System.out.print(task.get());
    }
}

对比:

  • Thread继承,比较难以扩散,Runnable实现容易扩充;
  • Thread类实现了Runnable接口;
  • Thraed类提供了start、run方法,Runnable只提供run方法;
  • Runnable需要通过Thread 类启动;
  • Callable提供call方法,有返回值;
    启动线程用Thread类的start方法;

3、线程运行状态

  • 创建——》启动:任何线程启动都需要Thread类的start()方法,但是启动之后并未执行,只是进入就绪状态;
  • 就绪——》执行:执行run方法之后从就绪到达执行状态,但是可能需要让出资源,进入阻塞状态,阻塞解除重新进入就绪状态;
  • 执行——》停止:如果run方法执行完,则停止

4、线程常用操作方法

(1)线程的命名与取得
实际开发中为了获取一些线程,只能通过线程名称来获得;

class XC implements Runnable{

	@Override
    public void run(){		
        System.out.println(Thread.currentThread().getName());
    } 
}

public class MyThread {
    
    public static void main(String args[]) throws InterruptedException, ExecutionException {
    	XC xc = new XC();
    	new Thread(xc,"xiancheng1").start();
    	new Thread(xc).start();

    }
}

如果存在耗时任务,可以交给线程处理,优先处理任务一和任务二;

    public static void main(String args[]) throws InterruptedException, ExecutionException {
    	System.out.println("任务1");
    	new Thread(()->{
    		for(int x = 0;x<Integer.MAX_VALUE;x++) {
    			
    		}
    	}).start();
    	System.out.println("任务2");

    }

(2)线程休眠
休眠结束自动唤醒,多线程并不是同时休眠和唤醒,是存在时间差的;

 public static void main(String args[]) throws InterruptedException, ExecutionException {
    	System.out.println("任务1");
    	new Thread(()->{
    		for(int x = 0;x<2;x++) {
    			try {
					Thread.sleep(1000);//休眠
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
    	    	System.out.println("任务...");

    		}
    	}).start();
    	System.out.println("任务2");

    }

(3)线程中断

  public static void main(String args[]) throws InterruptedException, ExecutionException {
    	Thread thread = new Thread(()->{
    			try {
					Thread.sleep(10000);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
    	    	
    	});
    	thread.start();
    	if(!thread.isInterrupted()) {//判断未中断
    		thread.interrupt();//中断线程
    	}
    }

(4)线程强制执行
某时候一个线程独占资源,需要强制执行;

 public static void main(String args[]) throws  InterruptedException {
    	Thread thread = new Thread(()->{
    		 
    			try {
					Thread.sleep(10000);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
    	    	
    	});
    	thread.start();
    	thread.join(); //强制中断
    }

(5)线程礼让
让出资源,别的线程先执行,每次礼让之让出一次当前资源;

 public static void main(String args[]) throws  InterruptedException {
    	Thread thread = new Thread(()->{
    		 for(int x = 0;x<3;x++) {
    			 try {
    			  if(x== 0) {
    					 Thread.yield(); //线程礼让
    				 }
 					Thread.sleep(100);
 					System.out.println("ha:"+x);
 				} catch (InterruptedException e) {
 					e.printStackTrace();
 				}
    		 }
    	});
    	thread.start();
    	
    	for(int x = 0;x<3;x++) {
			 try {
				Thread.sleep(100);
					System.out.println("hei:"+x);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		 }
    }

(6)线程优先级
理论上优先级越高,越先执行,但不一定最先执行默认创建的线程为中等优先级。
通过int类型数字设置优先级,有以下优先级:;
MAX_PRIORITY: 10;
NORM_PRIORITY: 5;
MIN_PRIORITY: 1;

  • 设置优先级

  • 获取优先级

 public static void main(String args[]) throws  InterruptedException {
    	Thread thread = new Thread(()->{
    		 for(int x = 0;x<3;x++) {
    			 try {
 					Thread.sleep(100);
 					System.out.println("ha:"+x);
 				} catch (InterruptedException e) {
 					e.printStackTrace();
 				}
    		 }
    	});
    	thread.start();
    	thread.setPriority(Thread.MAX_PRIORITY);//设置优先级
    	thread.getPriority();//获取优先级
    	
    }

5、线程的同步与死锁

当多个线程访问统一资源的时候,由于延迟等其他问题,导致线程数据不同步。

class XC implements Runnable{
	private int number = 10;
	@Override
	public void run(){
		while(true) {
//			synchronized(this) {
					if(this.number > 0) {
						try {
							Thread.sleep(100);
						} catch (InterruptedException e) {
							e.printStackTrace();
						}
					     System.out.println("已售票数:"+this.number--);
					} else {
					     System.out.println("票已售光");
					     break;
					}
//		    } 
		}	
	}
}

public class MyThread {
    
    public static void main(String args[]) throws  InterruptedException {
    	XC a = new XC();
    	new Thread(a,"A").start();
    	new Thread(a,"B").start();
    	new Thread(a,"C").start();

    }
}

结果:

已售票数:9
已售票数:8
已售票数:10
已售票数:7
已售票数:6
已售票数:5
已售票数:4
已售票数:3
已售票数:2
已售票数:1
票已售光
已售票数:0
票已售光
已售票数:-1
票已售光

(1)同步

  • 解决线程同步问题的关键是锁,当其中一个线程操作时,其他线程等待。
  • 利用关键字synchronized来实现,定义方法或代码块,里面的代码只允许一个线程执行。
class XC implements Runnable{
	private int number = 10;
	@Override
	public void run(){
		while(true) {
			synchronized(this) {//关键字,代码块
					if(this.number > 0) {
						try {
							Thread.sleep(100);
						} catch (InterruptedException e) {
							e.printStackTrace();
						}
					     System.out.println("已售票数:"+this.number--);
					} else {
					     System.out.println("票已售光");
					     break;
					}
		    } 
		}	
	}
}

public class MyThread {
    
    public static void main(String args[]) throws  InterruptedException {
    	XC a = new XC();
    	new Thread(a,"A").start();
    	new Thread(a,"B").start();
    	new Thread(a,"C").start();

    }
}

结果:

已售票数:10
已售票数:9
已售票数:8
已售票数:7
已售票数:6
已售票数:5
已售票数:4
已售票数:3
已售票数:2
已售票数:1
票已售光
票已售光
票已售光

  • 但是同步代码块会导致程序使用性能降低,此时需要同步方法解决,在同步方法上加上关键字synchronized即可。
class XC implements Runnable{
	private int number = 10;
	@Override
	public void run(){
		this.scal();
	}
	
	public  synchronized void scal() {//关键字,方法
		while(true) {
//			synchronized(this) {//关键字,代码块
					if(this.number > 0) {
						try {
							Thread.sleep(100);
						} catch (InterruptedException e) {
							e.printStackTrace();
						}
					     System.out.println(Thread.currentThread().getName()+"已售票数:"+this.number--);
					} else {
					     System.out.println("票已售光");
					     break;
					}
//		    } 
		}	
	}
}

public class MyThread {
    
    public static void main(String args[]) throws  InterruptedException {
    	XC a = new XC();
    	new Thread(a,"A").start();
    	new Thread(a,"B").start();
    	new Thread(a,"C").start();

    }
}

同步都会造成性能下降。
(2)死锁

  • 开发中出现的一种不确定状态,线程都在等待对方让出资源;
  • 若干线程访问同一资源时需要进行同步处理,过多的同步处理会造成死锁;

6、生产者与消费者模型

概念:

  • 生产者负责信息内容生产,当生产完成一个完整信息后,由消费者进行消费;
  • 如果生产者没有生产完成整个信息,消费者需要等待生产完成,反之如果消费者没有消费完成,生产者需要等待消费完成之后生产;

在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值