栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

爪哇(java)复习day13-2021/10/3

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

爪哇(java)复习day13-2021/10/3

多线程

程序:完成特定任务,由某种语言编写的代码。是一段静态代码。

进程:在内存中运行的一个应用程序

线程:进程执行的某一条路径

进程和线程的根本区别:进程是操作系统分配资源的基本单位,线程是处理器任务调度和执行的基本单元

一、Java中实现线程的四种方式:

1.继承Thread类

步骤:

①继承Thread类

②重写run方法

③声明子类对象

④调用start()方法

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


class MyThread extends Thread{
	public void  run() {
		// 1-100的偶数
		for(int i=1;i<=100;i++) {
			if(i % 2 ==0) {
				System.out.println(i);
			}
		}
	}
}

2.实现Runnable接口

步骤:

1.实现Runnbale接口

2.重写run方法

3.声明实现类对象

4.实现类对象作为Thread类构造器的参数,声明Thread类对象

5.Thread类对象调用start()方法

public class ThreadTset {
	public static void main(String[] args) {
		UThread uthread =new UThread();
		Thread t1=new Thread(uthread);
		
		t1.start();
		
	}
}

class UThread implements Runnable{
	public void run() {
		// 1-100的奇数
		for(int i=1;i<=100;i++) {
			if(i % 2 != 0) {
				System.out.println(i);
			}
		}
	}
}

3.实现Callable接口

步骤:

①实现Callable接口

②重写call()方法

③声明实现类对象

④实现类对象作为FutureTask类构造器的参数,声明FutureTask类对象

⑤FutureTask类的对象又作为Thread类构造器的参数,声明Thread的对象

⑥调用start()方法

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;

public class ThreadTset {
	public static void main(String[] args) throws InterruptedException, ExecutionException {
		MyThread thread=new MyThread();
		FutureTask task=new FutureTask(thread);
        Thread t1=new Thread(task);
        
        t1.start();
		System.out.println("sum + ="+task.get());
	}
}



class MyThread implements Callable{
	public Object call() {
		// 1-20偶数的和
		int sum=0;
		for(int i=1;i<=20;i++) {
			if(i % 2 == 0) {
				sum+=i;
				System.out.println(Thread.currentThread().getName()+"->"+i);
			}
		}
		return sum;
	}
}

 

 Callable接口与Runnable接口对比:

1.Callable接口支持泛型

2.call方法有返回值,可以抛出异常

public class ThreadTset {
	public static void main(String[] args) throws InterruptedException, ExecutionException {
		MyThread thread=new MyThread();
		FutureTask task=new FutureTask(thread);
        Thread t1=new Thread(task);
        
        t1.start();
		System.out.println("sum + ="+task.get());
	}
}



class MyThread implements Callable{
	public Integer call() throws Exception {
		// 1-20偶数的和
		int sum=0;
		for(int i=1;i<=20;i++) {
			if(i % 2 == 0) {
				sum+=i;
				System.out.println(Thread.currentThread().getName()+"->"+i);
			}
		}
		return sum;
	}
}

FutureTask中的get()方法返回call()方法的返回值

4.线程池:

使用线程池的好处:

①提高效率

②节省资源

③便于管理

Executors是一个工具类,作用:创建一个线程池

public class ThreadTset {
	public static void main(String[] args) throws InterruptedException, ExecutionException {
		ExecutorService cacheThreadPool=Executors.newCachedThreadPool();
		
		cacheThreadPool.execute(new Thread() {
			public void run() {
				for(int i=1;i<=20;i++) {
					if(i % 2==0) {
						System.out.println(i);
					}
				}
			}
		});
		
		cacheThreadPool.shutdown();
		
	}
}
 二、Thread类中的常用方法

1.currentThread():返回当前正在执行线程的对象

2.start():启动一个线程,执行run方法

3.run():让子类覆盖次方法,线程的任务

4.sleep(long time):让线程睡眠time毫秒

5.setName():设置线程的名字

6.getName():获取线程的名字

7.join():等待执行该方法的线程结束

8.yield():释放出cpu的执行权

9.stop():让线程结束

三、线程的声明周期

四、synchronized关键字
class Window extends Thread{
	private static int ticket=100;
	public void run() {
		while(true) {
			if(ticket>0) {
				try {
					Thread.sleep(100);
				} catch (InterruptedException e) {
					// TODO 自动生成的 catch 块
					e.printStackTrace();
				}
				System.out.println(Thread.currentThread().getName()+"卖出:"+ticket+"号票");
				ticket--;
			}else {
					break;
				}
		}
	}
}

public class ThreadTset {
	public static void main(String[] args) {
		Window w1=new Window();
		w1.setName("窗口1");
		
		Window w2=new Window();
		w2.setName("窗口2");
		
		Window w3=new Window();
		w3.setName("窗口3");
		
		w1.start();
		w2.start();
		w3.start();
	}
}

出现的问题:①同票 ②错票

出现问题的原因: 

窗口1、窗口2、窗口3同时对共享数据进行了操作

synchronized:

①修饰代码块

synchronized(同步监视器){

        // 同步监视器 : 任何一个类的对象都能充当同步监视器,相当于锁

        //多个对象需公用一把锁

        //类也是对象,且是唯一的

}

class Window extends Thread{
	private static int ticket=100;
	public void run() {
		while(true) {
			synchronized(Window.class) {
				if(ticket>0) {
					try {
						Thread.sleep(100);
					} catch (InterruptedException e) {
						// TODO 自动生成的 catch 块
						e.printStackTrace();
					}
					System.out.println(Thread.currentThread().getName()+"卖出:"+ticket+"号票");
					ticket--;
				}
			}else {
					break;
				}
		}
	}
}

public class ThreadTset {
	public static void main(String[] args) {
		Window w1=new Window();
		w1.setName("窗口1");
		
		Window w2=new Window();
		w2.setName("窗口2");
		
		Window w3=new Window();
		w3.setName("窗口3");
		
		w1.start();
		w2.start();
		w3.start();
	}
}

②修饰方法

class Window extends Thread{
	private static int ticket=100;
	public synchronized	void run() {
		while(true) {
//			synchronized(Window.class) {
				if(ticket>0) {
					try {
						Thread.sleep(100);
					} catch (InterruptedException e) {
						// TODO 自动生成的 catch 块
						e.printStackTrace();
					}
					System.out.println(Thread.currentThread().getName()+"卖出:"+ticket+"号票");
					ticket--;
				}
			}else {
					break;
				}
//		}
	}
}

public class ThreadTset {
	public static void main(String[] args) {
		Window w1=new Window();
		w1.setName("窗口1");
		
		Window w2=new Window();
		w2.setName("窗口2");
		
		Window w3=new Window();
		w3.setName("窗口3");
		
		w1.start();
		w2.start();
		w3.start();
	}
}

原因是: synchronized修饰方法,谁调用次方法谁就充当锁,一个对象一把锁。相当于synchronized(this){}

class Window1 implements Runnable{
	private int ticket=100;
	@Override
	public synchronized void run() {
		// TODO 自动生成的方法存根
		while(true) {
				if(ticket>0) {
					try {
						Thread.sleep(100);
					} catch (InterruptedException e) {
						// TODO 自动生成的 catch 块
						e.printStackTrace();
					}
					System.out.println(Thread.currentThread().getName()+"卖出:"+ticket+"号票");
					ticket--;
				}else {
					break;
				}
			}
	}
	
}

public class ThreadTset {
	public static void main(String[] args) {
		Window1 w1=new Window1();
	
		Thread t1=new Thread(w1);
		Thread t2=new Thread(w1);
		Thread t3=new Thread(w1);
		
		t1.setName("窗口1");
		t2.setName("窗口2");
		t3.setName("窗口3");
		
		t1.start();
		t2.start();
		t3.start();
	}
}
class Window1 implements Runnable{
	private int ticket=100;
	@Override
	public void run() {
		synchronized(this) {
		
			while(true) {
				if(ticket>0) {
					try {
						Thread.sleep(100);
					} catch (InterruptedException e) {
						// TODO 自动生成的 catch 块
						e.printStackTrace();
					}
					System.out.println(Thread.currentThread().getName()+"卖出:"+ticket+"号票");
					ticket--;
				}else {
					break;
				}
			}
		}
		// TODO 自动生成的方法存根
		
	}
	
}

public class ThreadTset {
	public static void main(String[] args) {
		Window1 w1=new Window1();
	
		Thread t1=new Thread(w1);
		Thread t2=new Thread(w1);
		Thread t3=new Thread(w1);
		
		t1.setName("窗口1");
		t2.setName("窗口2");
		t3.setName("窗口3");
		
		t1.start();
		t2.start();
		t3.start();
	}
}

五、ReentrantLock

import java.util.concurrent.locks.ReentrantLock;

public class ThreadTset {
	public static void main(String[] args) {
	    Window w1=new Window();
	    w1.setName("w1");
	    Window w2=new Window();
	    w2.setName("w2");
	    Window w3=new Window();
	    w3.setName("w3");
	    w1.start();
	    w2.start();
	    w3.start();
		
	}
}

class SingleTon{
	private SingleTon() {
		
	}
	private static ReentrantLock instance=new ReentrantLock();
	public static ReentrantLock getInstance() {
		return instance;
	}
}

class Window extends Thread{
	private static int ticket=100;
	ReentrantLock lock;
	{
		lock=SingleTon.getInstance();
	}
	public void run() {
		while(true) {
			try {
				lock.lock();	
				if(ticket>0) {
					
					System.out.println(Thread.currentThread().getName()+"->"+ticket);
					try {
						Thread.sleep(100);
					} catch (InterruptedException e) {
						// TODO 自动生成的 catch 块
						e.printStackTrace();
					}
					ticket--;
			}
			}catch(Exception e) {
				e.printStackTrace();
			}finally {
				lock.unlock();
			}
		}
	}
}

六、线程死锁问题

什么是死锁:我等待你释放资源,你等带我释放资源,彼此陷入了死循环中。

public class ThreadTset {
	public static void main(String[] args) {
		StringBuffer b1=new StringBuffer();
		StringBuffer b2=new StringBuffer();
		new Thread() {
			public void run() {
				synchronized(b1) {
					b1.append("a");
					b2.append(1);
					synchronized(b2) {
						b2.append("b");
						b2.append(2);
						System.out.println(b1);
						System.out.println(b2);
					}
				}
			}
		};
		
		new Thread() {
			public void run() {
				synchronized(b2) {
					b1.append("b");
					b2.append(3);
					synchronized(b1) {
						b1.append("d");
						b2.append(4);
						System.out.println(b1);
						System.out.println(b2);
					}
				}
			}
		};
	}
}

七、线程通信


public class ThreadTset {
	public static void main(String[] args) {
		Data data=new Data();
		Thread1 t1=new Thread1(data);
		t1.setName("t1");
		Thread2 t2=new Thread2(data);
		t2.setName("t2");
		
		t1.start();
		t2.start();
		
	}
}

class Data{
	private  int count=1;

	
	
	public int getCount() {
		return count;
	}

	public synchronized void method1() {
		// TODO 自动生成的方法存根
		if(count<=100) {
			notify();
			System.out.println(Thread.currentThread().getName()+"->"+count);
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				// TODO 自动生成的 catch 块
				e.printStackTrace();
			}
			count++;
			try {
				wait();
			} catch (InterruptedException e) {
				// TODO 自动生成的 catch 块
				e.printStackTrace();
			}
		}
	}

	public synchronized void method2() {
		// TODO 自动生成的方法存根
		if(count<=100) {
			notify();
			System.out.println(Thread.currentThread().getName()+"->"+count);
			try {
				Thread.sleep(100);
			} catch (InterruptedException e) {
				// TODO 自动生成的 catch 块
				e.printStackTrace();
			}
			count++;
			try {
				wait();
			} catch (InterruptedException e) {
				// TODO 自动生成的 catch 块
				e.printStackTrace();
			}
		}
	}
}

class Thread1 extends Thread{
	Data data;
	public Thread1(Data data) {
		this.data=data;
	}
	public void run() {
		while(true) {
			data.method1();
			if(data.getCount()>100)
				break;
		}
	}
}
class Thread2 extends Thread{
	Data data;
	public Thread2(Data data) {
		this.data=data;
	}
	public void run() {
		while(true) {
			data.method2();
			if(data.getCount()>100)
				break;
		}
	}
}

线程通信之生产者消费者问题:

public class ThreadTset {
	public static void main(String[] args) {
	   Clerk c=new Clerk();
	   Producer producer=new Producer(c);
	   Consume consume=new Consume(c);
	   producer.setName("producer");
	   consume.setName("consume");
	   producer.start();
	   consume.start();
	}
}

class Clerk{
	private int product=0;

	public int getProduct() {
		return product;
	}

	public synchronized void productItem() {
		// TODO 自动生成的方法存根
		if(product<20) {
			product++;
			System.out.println(Thread.currentThread().getName()+"生產第"+product+"號產品");
			notify();
		}else {
			try {
				wait();
			} catch (InterruptedException e) {
				// TODO 自动生成的 catch 块
				e.printStackTrace();
			}
		}
	}

	public synchronized void consumeItem() {
		// TODO 自动生成的方法存根
		if(product>0) {
			System.out.println(Thread.currentThread().getName()+"消費第"+product+"號產品");
			product--;
			notify();
		}else
		{
			try {
				wait();
			} catch (InterruptedException e) {
				// TODO 自动生成的 catch 块
				e.printStackTrace();
			}
		}
	}
	
}
class Producer extends Thread{
	private Clerk clerk;
	public Producer(Clerk clerk) {
		this.clerk=clerk;
	}
	public void run() {
		while(true) {
			clerk.productItem();
			try {
				Thread.sleep(10);
			} catch (InterruptedException e) {
				// TODO 自动生成的 catch 块
				e.printStackTrace();
			}
		}
	}
}
class Consume extends Thread{
	private Clerk clerk;
	public Consume(Clerk clerk) {
		this.clerk=clerk;
	}
	public void run() {
		while(true) {
			clerk.consumeItem();
			try {
				Thread.sleep(10);
			} catch (InterruptedException e) {
				// TODO 自动生成的 catch 块
				e.printStackTrace();
			}
		}
	}
}

sleep与wait方法的比较:

①两者都是让线程阻塞

②sleep方法是Thread类中的静态方法,调用sleep方法并不释放锁

③wait方法是Object类中的方法,必须使用在synchronized修饰的方法或者代码块中,调用wait方法会释放锁

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/287605.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号