线程与进程

概述

进程

概述:运行起来的程序就是进程

特点:进程与进程之间的资源是独立的,操作系统分配的基本单位

多进程:同时可以运行多个程序,“宏观并行,微观串行”

线程

概述:进程里面的一条执行路径;如果有多条执行路径,则是多线程

现实中的进程与线程:

进程: QQ音乐,再执行迅雷下载

线程:迅雷中分多条执行路径下载大片;特点:在该进行中多线程会互抢资源

进程与线程区别

进程是系统分配的基本单位; 线程是cpu调度的基本单位

一个进程一般会有多个线程,至少有一个线程

进程间的资源是独立的; 进程中的多个线程资源是共享的

线程创建

继承Thread

//线程的创建:继承Thread
//案例:主线程(main的执行路径)和子线(创建的)程都打印1~200;查看执行的结果
class MyThread extends Thread{
	@Override
	public void run() { //run中的执行就是子线程的执行
		for(int i=1;i<=200;i++) {
			System.out.println("子线程..."+i);
		}
	}
}
public class Test1 {
	public static void main(String[] args) {
		//创建子线程的注意事项:1.子线程的创建要放到主线程执行前面  2.调start方法
		MyThread thread = new MyThread();
		//将当前线程对象放入线程组,供cpu调度;当cpu调度到你,则你执行;调度到其他线程,则就绪状态
		thread.start();
		//thread.start(); //new一次线程对象,不能多次调用,否则报错
		
		new MyThread().start(); //new次new,多次调用,则不会有问题
		
		for(int i=1;i<=200;i++) {
			System.out.println("主线程..."+i);
		}
	}
}

实现Runnable

class Task implements Runnable{
	@Override
	public void run() {
		for(int i=1;i<=200;i++) {
			System.out.println("子线程..."+i);
		}
	}
}
public class Test2 {
	public static void main(String[] args) {
		Thread th = new Thread(new Task()); //传入任务对象
		th.start();
		
		for(int i=1;i<=200;i++) {
			System.out.println("主线程..."+i);
		}
	}
}

线程的方法

优先级与sleep

线程的优先级,可以改变线程的执行的效率;但不是绝对性可以改变哪个线程先执行完

//线程的优先级: 优先级高,则大概率先执行完,但不绝对
//案例:两个子线程都打印1~200;查看执行的结果
class MyThread extends Thread{
	public  MyThread(String name) {
		super(name); //值传给父类
	}
	@Override
	public void run() {
		for(int i=1;i<=200;i++) {
			try {
				Thread.sleep(1); //睡眠-单位毫秒; 好处复现线程抢占效果
			} catch (InterruptedException e) {}
			
			System.out.println(getName()+"..."+i);  //调用父类name值
		}
	}
}
public class Test1 {
	public static void main(String[] args) {
		MyThread thread = new MyThread("线程1");
		thread.setPriority(Thread.MAX_PRIORITY); //设置高优先级
		thread.start();
		
		MyThread thread2 = new MyThread("线程2");
		thread2.setPriority(Thread.MIN_PRIORITY); //设置低优先级
		thread2.start();
	}
}

线程礼让

线程礼让yield:中断当次线程,继续和其他资源争抢; 礼让的线程相对会执行的慢一些,但不是绝对性的。

//线程的礼让:
//案例:两个子线程都打印1~200;其中一个线程每次执行都进行礼让,查看执行的结果
class A extends Thread{
	@Override
	public void run() {
		for(int i=1;i<=200;i++) {
			Thread.yield();  //线程礼让;理论上会执行得慢一点
			System.out.println("线程A..."+i); 
		}
	}
}
class B extends Thread{
	@Override
	public void run() {
		for(int i=1;i<=200;i++) {
			System.out.println("线程B..."+i); //调用父类name值
		}
	}
}
public class Test2 {
	public static void main(String[] args) {
		new A().start();
		new B().start();
	}
}

线程合并

线程合并join,也叫插队; 插队的线程绝对性的先执行完

应用场景: 子线程插主线程的队

//线程插队:
//案例:子线程和主线程各打印1~200;主线程执行到5,让子线程插队先执行完,查看执行的结果
class MyTh extends Thread{
	@Override
	public void run() {
		for(int i=1;i<=200;i++) {
			System.out.println("子线程..."+i); 
		}
	}
}
public class Test3 {
	public static void main(String[] args) throws InterruptedException {
		MyTh th = new MyTh();
		th.start();
		
		for(int i=1;i<=200;i++) {
			System.out.println("主线程线程..."+i); 
			if(i==5) {
				th.join();  //子线程插队
			}
		}
	}
}

线程安全

在多线程中,出现了共享数据,需要加锁处理;锁的注意事项: 1.同一个锁对象 2.锁的范围

案例:买票系统,5个窗口共卖1000张票;观察卖票过程:

继承Thread

class MyThread extends Thread{
	private static int ticket = 1000;  //1000张票-共享数据 
	
	public  MyThread(String name) {
		super(name);
	}
	@Override
	public void run() {
		while(true) { 
			//同步代码块方式
			synchronized ("lock") { 
				if(ticket>0) {
					System.out.println(getName()+"正在卖第"+ticket+"张票");
					ticket--;
				}else {
					System.out.println(getName()+"已经卖完了");
					break;
				}
			}
		}
	}
}
public class Test2 {
	public static void main(String[] args) {
		for(int i=1;i<=5;i++) {
			new MyThread("窗口00"+i).start();
		}
	}
}

实现Runnable

public class Test1 {
	public static void main(String[] args) {
		Task task = new Task();
		for(int i=1;i<=5;i++) {
			new Thread(task,"窗口"+i).start();
		}
	}
}
class Task implements Runnable{
	private int ticket = 1000;  //1000张票-共享数据 
	@Override
	public void run() {
		while(true) {  
			//同步代码块方式
			synchronized (this) { //"lock"  静态对象
				if(ticket>0) {
					//Thread.currentThread().getName():实现任务获取的线程名
					System.out.println(Thread.currentThread().getName()+"正在卖第"+ticket+"张票");
					ticket--;
				}else {
					System.out.println(Thread.currentThread().getName()+"已经卖完了");
					break;
				}
			}
		}
	}

 

死锁

有一个线程进入到锁里后,没有退出;其他的线程进不去,则构成死锁

同步代码块和同步方法都是自动释放锁资源,所以不容易出现死锁;如果需要演示死锁案例;在同步锁中需要进行锁嵌套;

注意:此处只是为了测试死锁,才进行的锁嵌套; 以后使用时尽量避免锁嵌套(避免死锁)

//死锁案例:两个线程,各自执行自身的代码
class MyThread extends Thread{
	private boolean a;  //标记判断
	public MyThread(boolean a) {
		this.a = a;
	}
	@Override
	public void run() {
		if(a) {
			synchronized ("A") { //线程1
				System.out.println("进入线程1的A锁");
				synchronized ("B") {
					System.out.println("进入线程1的B锁");
				}
			}
		}else {
			synchronized ("B") { //线程2
				System.out.println("进入线程2的B锁");
				synchronized ("A") {
					System.out.println("进入线程2的A锁");
				}
			}
		}
	}
}
public class Test1 {
	public static void main(String[] args) {
		new MyThread(true).start();  //线程1
		
		new MyThread(false).start(); //线程2
	}
}

线程池

线程池:就是装线程的容器,预先在容器中创建指定个数的线程对象;当用户需要时,直接从容器中获取;用完了,再回收到线程池中。

之前创建线程的方式:创建线程对象后,执行完毕则销毁线程对象;如果程序中需要频繁创建线程时,会非常影响性能及消耗内存的资源

好处:减少了创建和销毁线程的数目,提升了性能及减少了资源的消耗

线程池的复用机制:线程对象使用完后,重新再回到线程池;可以交给其他用户继续使用

内部实现: 创建集合;集合中都是存线程对象;有用户使用,则移除当前集合元素;用完后,则添加回集合中。

class Task implements Runnable{
	@Override
	public void run() {
		for(int i=1;i<=10;i++) {
			System.out.println(Thread.currentThread().getName()+"-->"+i);
		}
	}
}
public class Test1 {
	public static void main(String[] args) {
		//在线程池中创建单个线程对象,通过单个线程对象去处理多个任务
		//ExecutorService es = Executors.newSingleThreadExecutor();
		//带缓冲区的线程池:有多少个任务,则会产生多少个线程对象的处理
		//ExecutorService es = Executors.newCachedThreadPool();
		//带复用机制的线程池:指定线程池个数,进行复用
		ExecutorService es = Executors.newFixedThreadPool(2);//(常用)
		es.submit(new Task()); //任务接口Runnable
		es.submit(new Task());
		es.submit(new Task());  //有三个任务,则谁先执行完,再执行第3个--复用
		
		es.shutdown();  //线程池的终止
	}
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值