欢迎查看多线程

进程和线程的区别

1、进程是资源分配最小单位,线程是程序执行的最小单位;

2、进程有自己独立的地址空间,每启动一个进程,系统都会为其分配地址空间,建立数据表来维护代码段、堆栈段和数据段,线程没有独立的地址空间,它使用相同的地址空间共享数据;

3、CPU切换一个线程比切换进程花费小;

4、创建一个线程比进程开销小;

5、线程占用的资源要⽐进程少很多。

6、线程之间通信更方便,同一个进程下,线程共享全局变量,静态变量等数据,进程之间的通信需要以通信的方式(IPC)进行;(但多线程程序处理好同步与互斥是个难点)

7、多进程程序更安全,生命力更强,一个进程死掉不会对另一个进程造成影响(源于有独立的地址空间),多线程程序更不易维护,一个线程死掉,整个进程就死掉了(因为共享地址空间);

8、进程对资源保护要求高,开销大,效率相对较低,线程资源保护要求不高,但开销小,效率高,可频繁切换;

创建线程的两种方法

继承Thread类

在这里插入图片描述

实例代码(开发一个线程类,该类的构造方法参数是线程名称,该线程的功能是从1打印到1000。)

public class A {
	public void go() {
		for(int i=0;i<=1000;i++) {
			System.out.println(Thread.currentThread().getName()+":"+i);
		}
		
	}
}
public class One extends Thread{
	public One(String name) {
		super(name);
	}
	
	@Override
	public void run() {
		for(int i=0;i<=1000;i++) {
			System.out.println(this.getName()+":"+i);
		}
	}

}
public class Two extends A implements Runnable {
	@Override
	public void run() {
		this.go();
	}
}
public class Main {
	public static void main(String[] args) {
		Thread t0 = Thread.currentThread();
		Thread t1 =new One("A");
		t1.start();
		Thread t2 =new Thread (new Two(),"B");
		t2.start();
		for(int i=1;i<=1000;i++) {
			System.out.println(t0.getName()+":"+i);
			try {
				Thread.sleep(1);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		System.out.println(t0.getName()+"结束");
	}
}

实现Runnable接口

在这里插入图片描述

实例代码(二、开发一个功能类(该类未继承Thread类),该类有一个公有实例方法,功能为从201打印到300;再实现一个线程,该线程的父类是功能类,该线程的功能通过调用父类的功能方法实现。)

public class A extends Thread{
	public  A(String name) {
		super(name);
	}
	@Override
	public void run() {
		for(int i=1;i<=100;i++) {
			System.out.println(this.getName()+":"+i);
//			try {
//				Thread.sleep(10);
//			} catch (InterruptedException e) {
//				// TODO Auto-generated catch block
//				e.printStackTrace();
//			}		
		}
	}
}
public class B extends GongNeng implements Runnable {
	
	private Thread t0;
	B(Thread t0){
		this.t0=t0;
	}
	@Override
	public void run() {
		this.go(t0);
	}
}
public class GongNeng {
	public void go(Thread t) {
		for(int i=201;i<=300;i++) {
			
//			try {
//				Thread.sleep(10);
//			} catch (InterruptedException e) {
//				// TODO Auto-generated catch block
//				e.printStackTrace();
//			}
			System.out.println(Thread.currentThread().getName()+":"+i);
			
			if(i==220) {
				try {
					t.join();
					
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();			
			}
			}
		}
	}
}
public class Test {
	public static void main(String[] args) {
		Thread t0 =new A("A");
		Thread t1 =new Thread(new B(t0),"B");
		t0.start();
		t1.start();
	}
}

线程同步

实例

public class PrintString {
	private static Object lock =new Object();
	private String str;
	public PrintString(String str) {
		super();
		this.str = str;
	}
	public void pr() {	
		synchronized (lock) {
			for(int i=0;i<str.length();i++) {
				System.out.println(Thread.currentThread().getName()+":"+str.charAt(i));
				try {
					Thread.sleep(1);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
	}
}
public class Test {
	public static void main(String[] args) {
		
		PrintString p1 =new PrintString("hello!大家好!");
		PrintString p2 =new PrintString("hello!祝大家中秋节快乐!");
		
		new Thread("线程1:") {
			@Override
			public void run() {
				p1.pr();
			}
			
		}.start();
		
		new Thread("线程2:") {
			@Override
			public void run() {
				p2.pr();
			}
			
		}.start();
		
	}

}

线程协作

实例

在这里插入图片描述

代码

public class MB {
	private int size;
	private int maxSize;
	public MB( int maxSize) {
		this.maxSize = maxSize;
	}
	public synchronized void chan() {
		while(this.isFull()) {
			try {
				System.out.println(Thread.currentThread().getName()+"面包库已经存储满了!请停止生产*********************");
				this.wait();
				System.out.println(Thread.currentThread().getName()+"被唤醒了##############");
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			
		}
		size++;
		System.out.println(Thread.currentThread().getName()+"生产了一块面包,现在面包数量为:"+size);
		this.notifyAll();
		Thread.yield();
		
	}
	
	public synchronized void mai() {
		while(this.isEmpty()) {
			
			
			try {
				System.out.println(Thread.currentThread().getName()+"面包已经卖完啦!请等待**********************");
				this.wait();
				System.out.println(Thread.currentThread().getName()+"被唤醒了###############");
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			
		}
		size--;
		System.out.println(Thread.currentThread().getName()+"卖了一块面包,现在面包数量为:"+size);
		this.notifyAll();
		Thread.yield();
		
	}
	
	public boolean isEmpty() {
		return size==0;
	}
	
	public boolean isFull() {
		return size==maxSize;
	}
}
public class Test {
	public static void main(String[] args) {
		MB m =new MB(5);
		
		for (int i = 0; i < 100; i++) {
			new Thread("生产厂家:") {
				public void run() {
					for (int j = 0; j < 20; j++) {
						m.chan();
					}
				};

			}.start();		
			
			new Thread("消费者:") {

				public void run() {
					for (int j = 0; j <20; j++) {
						m.mai();
					}
				};
			}.start();
		}
	}
}

线程中常用的方法

1、线程部分方法详解

在这里插入图片描述

2、线程启动

在这里插入图片描述

3、守护线程

在这里插入图片描述

4、线程同步的概念

在这里插入图片描述

5、线程的同步互斥

在这里插入图片描述

6、线程协作

在这里插入图片描述

7、实现线程同步的方法有哪些

同步代码块
同步实例方法
同步类方法(静态方法)

8、sleep()方法和wait()方法的区别

一.查看API

sleep是Thread类的方法,导致此线程暂停执行指定时间,给其他线程执行机会,但是依然保持着监控状态,过了指定时间会自动恢复,调用sleep方法不会释放锁对象。

wait方法是Object类里的方法,当一个线程执行到wait()方法时,它就进入到一个和该对象相关的等待池中,同时释放了锁对象,等待期间可以调用里面的同步方法,其他线程可以访问,等待时不拥有CPU的执行权,否则其他线程无法获取执行权。

二.是否可以传入参数

sleep()方法必须传入参数,参数就是休眠时间,时间到了就会自动醒来。
wait()方法可以传入参数也可以不传入参数,传入参数就是在参数结束的时间后开始等待,不穿如参数就是直接等待。

三.是否需要捕获异常

sleep方法必须要捕获异常,而wait方法不需要捕获异常。

四.作用范围

wait、notify和notifyAll方法只能在同步方法或者同步代码块中使用,而sleep方法可以在任何地方使用。
五.是否释放锁
sleep方法继续持有锁,
wait方法则释放锁

发布了5 篇原创文章 · 获赞 8 · 访问量 309

猜你喜欢

转载自blog.csdn.net/weixin_44989103/article/details/101150868