Java基础之线程

Java基础

线程

  1. 简介
    程序:静态的代码
    进程:程序动态的执行过程,产生,执行,消亡
    线程:进程内最小的执行单位,动态执行的过程
    进程有自己独立的内存
    线程共享进程的资源,在进程内,每个线程可以完成独立的功能
    进程和线程关系图如下:
    线程和进程
  2. 线程创建的两种方式
    2.1 继承Thread类:线程类
    2.2 实现Runnable接口: 不是线程类
    注意:线程代码要写到run()方法里
    在主线程里启动线程start()方法,启动了才能执行
    代码小示 ^ _ ^ :
	package com.java.day12_3;
	//继承Thread类的方式创建线程
	class T1 extends Thread{
		//线程完成功能代码要写到线程体方法中,run()方法
		@Override
		public void run() {
			for(int i = 0; i < 100; i++) {
				System.out.println("hello");
			}
		}
	}
	class T2 extends Thread{
		//线程完成功能代码要写到线程体方法中,run()方法
		@Override
		public void run() {
			for(int i = 0; i < 100; i++) {
				System.out.println("Thread");
			}
		}
	}
	public class MyThread {
		
		//主线程
		public static void main(String[] args) {
			T1 t1 = new T1();
			T2 t2 = new T2();
			t1.start();
			t2.start();
		}
	
	}
package com.java.day13;
//实现Runnable接口的方式创建线程
//Runnable1并不是线程类
//Runnable是函数式接口,可以用lambda表达式
class Runnable1 implements Runnable{

	@Override
	public void run() {
		for(int i = 1; i <= 10; i++) {
			System.out.println(i);
		}
	}
}

public class Demo {

	public static void main(String[] args) {
		Runnable1 r = new Runnable1();
		Thread t = new Thread(r);
		t.start();
		Thread t2 = new Thread(()->{//lambda表达式
			for(int i = 1; i <= 10; i++) {
				System.out.println("hello");
			}
		});
		t2.start();
	}

}

  1. 线程的常用方法
    Thread.currentThread() ---------获取当前线程对象
    getName() ---------获取当前线程名字
    getId() --------获取当前线程id
    isAlive() ---------判断当前线程是否还活着(能用)
package com.java.day13;

public class Demo3 {

	public static void main(String[] args) {
		Thread t1 = new Thread(){
			public void run() {
				System.out.println(Thread.currentThread());//Thread[线程1,5,main] 名字,优先级,所处线程
				System.out.println(getName());//线程1 名字
				System.out.println(getId());//10 id
				System.out.println(isAlive());//true 活着
			}
		};
		t1.setName("线程1");
		t1.start();
		
		System.out.println(Thread.currentThread());//Thread[main,5,main]
		System.out.println(Thread.currentThread().getName());//main
		System.out.println(Thread.currentThread().getId());//1
		System.out.println(Thread.currentThread().isAlive());//true
	}

}

Thread.sleep(毫秒数);---------线程休眠多少毫秒

package com.java.day13;

public class Demo4 {
	/**
	 * sleep(毫秒):线程休眠 
	 * 如果休眠的过程中被唤醒,会抛出InterruptedException
	 */
	public static void main(String[] args) {
		new Thread(()->{
			System.out.println(Thread.currentThread().getName());
			for(int i = 10; i >= 0; i--) {
				if(i != 0) {
				System.out.println(i);
				}else {
					System.out.println("过年了!");
				}
				try {
					Thread.sleep(1000);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		},"线程sleep").start();
	}

}

join();---------当前线程等待其他线程先执行

package com.java.day13;
//模拟图片显示和图片下载
public class Demo5 {
	/**
	 * join();
	 * 当前线程等待其他线程先执行
	 */
	public static void main(String[] args) {
		//图片下载的线程
		Thread t1 = new Thread() {
			@Override
			public void run() {
				System.out.println("正在下载中");
				for(int i = 0; i <= 100; i++) {
					System.out.println(i+"%");
					try {
						Thread.sleep(100);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
			}
		};
		//图片显示的线程
		Thread t2 = new Thread(()->{
			//for(int i = 0; i <= 10; i++) {
			//	System.out.println("Thread-2:"+i);
			//	if(i == 3) {
			//		try {
			//			t1.join();
			//		} catch (InterruptedException e) {
			//			e.printStackTrace();
			//		}
			//	}
			//}
			System.out.println("图片显示");
			try {
				t1.join();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			System.out.println("图片显示成功");
		});
		
		t2.start();
		t1.start();
	}

}
  1. 守护线程
    setDeamon(true);
    创建出来的线程:用户线程(前台线程)和守护线程(后台线程)。
    设置守护线程,要调用setDeamon(true);
    守护线程和用户线程的用法和创建方式没有区别。
    两者的区别:用户线程执行完毕,守护线程无条件停止执行。
	package com.java.day13;
	/*
	 * 守护线程
	 */
	public class Demo6 {
		/**
		  *  模拟泰坦尼克号  you jump! I jump!
		 */
		public static void main(String[] args) {
			
			Thread rose = new Thread() {
				@Override
				public void run() {
					for(int i = 0; i < 3; i++) {
						System.out.println("一起跳!");
						try {
							Thread.sleep(1000);
						} catch (InterruptedException e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						}
					}
					System.out.println("扑通...");
				}
			};
			
			Thread jeck = new Thread(()->{
				while(true) {
					System.out.println("你先跳!我再跳!");
					try {
						Thread.sleep(1000);
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}
			});
	
			rose.start();
			jeck.setDaemon(true);//在启动线程之前设置线程为守护线程
			jeck.start();
		}
	
	}
  1. 线程的生命周期
    从生到死的几个阶段:
    新建状态:new Thread() 可以有两个选择:完成使命start(),直接消亡
    就绪状态:调用start()
    阻塞状态:调用sleep()、wait()、等待加载资源等,让出CPU资源
    运行状态:执行run()
    消亡:执行完run()中的语句
    注意:调用sleep醒了之后,重新处于就绪状态
  2. 线程的优先级
    不同优先级:高优先级先执行,低优先级后执行(高优先级具备了先执行的权利,但不一定先执行)。
    同一优先级:先到先服务。
    线程优先级的规范:系统默认线程的优先级为中等优先级;人为设置线程的优先级。
    人为设置优先级:setPriority(常量值);常量值有MIN_PRIORITY、NORM_PRIORITY、MAX_PRIORITY
package com.java.day13;

public class Demo7 {

	public static void main(String[] args) {
		Thread t1 = new Thread(()->{
			for(int i = 0; i <= 10; i++) {
				System.out.println("t1");
			}
		});
		Thread t2 = new Thread(()->{
			for(int i = 0; i <= 10; i++) {
				System.out.println("t2");
			}
		});
		Thread t3 = new Thread(()->{
			for(int i = 0; i <= 10; i++) {
				System.out.println("t3");
			}
		});
		
		t1.setPriority(Thread.MIN_PRIORITY);
		t2.setPriority(Thread.NORM_PRIORITY);
		t3.setPriority(Thread.MAX_PRIORITY);
		t1.start();
		t2.start();
		t3.start();
	}

}
  1. 线程同步
    当多个线程操作一个共享变量时,可能会造成共享变量的不安全性(如共享变量为1且该变量应该大于等于0,两个线程对变量进行减1操作,第一个线程减1后还没来得及改为0,第二个线程以为还是1也进行了减1操作,最终这个变量变成了-1)。

    为了确保共享变量的安全性,使用同步机制保证共享变量的安全性。

    同步机制:当一个线程改变共享变量值的时候,其他线程不能使用共享变量,当线程计算完成,返回变量值之后,其他线程才可以使用共享变量。

    使用 synchronized关键字实现线程同步,下面是两种方式:
    第一种:
    同步块 synchronized(锁对象){
    共享变量相关的业务代码(运算)
    }
    第二种:
    在方法上添加synchronized,用此关键字修饰的方法叫同步方法。

package com.java.day13;
/**
 *	模拟窗口买票
 *	一个窗口即为一个线程
 */
class TicketThread extends Thread{
	public void run() {
		while(true) {
			synchronized (Demo8.class) {//同步块
				if(Demo8.ticket <= 0) {
					try {
						throw new Exception("票卖完了");
					} catch (Exception e) {
						System.out.println(e.getMessage());
						break;
					}
				}else {
						Demo8.ticket--;
						System.out.println(Thread.currentThread().getName()+" 卖了一张票,还剩"+Demo8.ticket+"张");
					try {
						Thread.sleep(1000);
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}
			}
		}
	};
}
public class Demo8 {
	static int ticket = 3;
	public static void main(String[] args) {
		TicketThread t1 = new TicketThread();
		TicketThread t2 = new TicketThread();
		TicketThread t3 = new TicketThread();
		TicketThread t4 = new TicketThread();
		TicketThread t5 = new TicketThread();
		TicketThread t6 = new TicketThread();
		t1.start();
		t2.start();
		t3.start();
		t4.start();
		t5.start();
		t6.start();
	}

}
	package com.java.day13;
	/**
	 * 模拟两个人往一个银行账户存钱
	 */
	class Bank{
		int money = 100;
		public synchronized void save(int money) {
			for(int i = 0; i < 3; i++) {
				this.money += money;
				System.out.println(Thread.currentThread().getName()+"存钱"+money);
				System.out.println("账户余额为"+this.money);
				try {
					Thread.sleep(1000);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
	}
	public class Demo10 {
	
		public static void main(String[] args) {
			Bank bank = new Bank();
			Thread t1 = new Thread(()->{
				bank.save(1000);
			});
			Thread t2 = new Thread(()->{
				bank.save(1000);
			});
			t1.start();
			t2.start();
		}
	
	}
  1. 同步线程中的通信
    wait();
    notify();
    notifyAll();
	package com.java.day13;
	/**
	 * 	两个线程交替打印1-10
	 * 	wait();
	 *	notify();
	 */
	class CountThread implements Runnable{
		int i = 1;
		@Override
		public void run() {
			synchronized (this) {
				while(i <= 10) {
					notify();//唤醒wait的线程
					System.out.println(Thread.currentThread().getName()+":"+i);
					i++;
					try {
						Thread.sleep(1000);
					} catch (InterruptedException e1) {
						// TODO Auto-generated catch block
						e1.printStackTrace();
					}
					try {
						if(i > 10)
							break;
						wait();//等待
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}
			}
		}
		
	}
	
	public class Demo11 {
	
		public static void main(String[] args) {
			CountThread ct = new CountThread();
			Thread t1 = new Thread(ct);
			Thread t2 = new Thread(ct);
			t1.start();
			t2.start();
		}
	
	}
  1. sleep和wait的区别
sleepwait
是线程类的方法是object的方法
不是释放锁是释放锁
自动醒必须使用notify,notifyAll唤醒
  1. 线程的死锁
  2. 线程池
    频繁的创建线程,需要耗费时间和内存,使用线程池可以使线程重用,还可以管理线程。
    ExecutorService t = Executors.newCashedThreadPool();
    t.execute();
    ExecutorService t = Executors.newFixedThreadPool(3);//指定线程池的线程数
    t.shutdown();//不关闭正在执行的线程
    t.shutdownNow();//不管线程执没执行完,运行到这条语句就关闭线程池
  3. 练习
    开发者 - 消费者
    当有产品时(即产品数>0),消费者可以买产品,当没有产品时,告诉生产者,让他生产产品。
package com.java.day13;
/**
 *	商品管理者
 */
public class Manager {
	int protect = 10;
	//生产商品
	public synchronized void makeProtect() {
		if(protect <= 0) {
			protect++;
			System.out.println(Thread.currentThread().getName()+"生产了一件商品");
		}else{
			notifyAll();
			try {
				wait();
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
	//获得商品
	public synchronized void getProtect() {
		if(protect > 0) {
			protect--;
			System.out.println(Thread.currentThread().getName()+"买商品");
		}else {
			notifyAll();
			try {
				wait();
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
}

package com.java.day13;
/**
 * 商品生产者
 */
public class Producer implements Runnable{
	private Manager manager;
	public Producer(Manager manager) {
		this.manager = manager;
	}
	@Override
	public void run() {
		while(true) {
			manager.makeProtect();
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			}
		}
	}
	
}

package com.java.day13;
/**
 * 	消费者
 */
public class Consumer implements Runnable{
	private Manager manager;
	public Consumer(Manager manager) {
		this.manager = manager;
	}
	@Override
	public void run() {
		
		while(true) {
			manager.getProtect();
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
		}
		
	}

}

package com.java.day13;
/**
 * 测试类
 */
public class Test {

	public static void main(String[] args) {
		Manager manager = new Manager();
		Thread t1 = new Thread(new Producer(manager));
		Thread t2 = new Thread(new Consumer(manager));
		t2.start();
		t1.start();
	}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值