线程和进程
进程(Process)是计算机中的程序关于某数据集合一次运动活动,是系统进行资源调度和分配的基本单位,是操作系统结构的基础
线程(Thread)是操作系统能够运行运算调度的最小单位,它被包含在进程(Process)之中,是进程的实际运作单位,一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每个线程并行执行不同的任务。
线程的生命周期
NEW 新建状态
RUNNABLE 运行状态
BLOCKED 阻塞状态
WAITTING 等待状态(一直等待 无线等待)
TIME_WAITTING 超时等待
TERMINATED终止状态,当线程结束完成后就会变成终止状态
线程的实现三种方法
1.继承Thread类
方法:public void run(),必须重新run方法
实现步骤
- 自定义一个类,继承自Thread类
- 在自定义的类中重新Thread的run()方法
- 在main()中创建线程
实现案例
public class MyThread extends Thread{//继承Thread类 @Override public void run() {//重写run()方法 for(int x = 0;x<20;x++){ System.out.println(getName()+":"+x);//getName()获取线程名字 } } } public class MyThreadTest { public static void main(String[] args) { MyThread mt1= new MyThread();//创建第一个线程 MyThread mt2 = new MyThread();//创建第二个线程 mt1.setName("线程一");//给第一个咸亨设置名字 mt2.setName("线程二");//给第二个线程设置名字 mt1.start();//第一个线程启动 mt2.start();//第二个线程启动 } }
2.实现Runnable接口
实现步骤
- 自定义一个类,实现Runnable接口,重写里面的run()方法
- 在main中创建实现Runnable接口实现类,就是资源对象类
- 启动线程
实现案例
public class MyRunnbale implements Runnable{//实现Runnable接口 @Override public void run() {//重写run()方法 for (int x= 0;x<10;x++){ System.out.println(Thread.currentThread().getName()+":"+x); } } } public class MyRunnableTest { public static void main(String[] args) { MyRunnbale mr = new MyRunnbale();//创建资源类对象 //创建两条线程 Thread t1 = new Thread(mr,"t1"); Thread t2 = new Thread(mr,"t2"); //启动两个线程 t1.start(); t2.start(); } }
public Thread(Runnable target,String name):参数1:接口(传递接口子实现类对象) ,参数2:线程名字
3.线程池
线程池(Thread Pool)是多线程处理形式,处理过程中将任务添加到队列,然后在创建线程后自动启动这些任务。线程池线程都是后台线程。
public static ExecutorService newFixedThreadPool(int nThreads)创建一个固定的可重用的线程数的线程池,返回值是一个子实现类
<T> Future<T> submit(Callable<T> task):提交异步任务,并返回结果处理
实现步骤
- 创建线程池 Executors public static ExecutorService newFixedThreadPool(int nThreads)创建
- 提交异步任务
- 关闭线程池
实现案例
public class MyCallable implements Callable { @Override public Object call() throws Exception { for (int x = 0;x<=30;x++){ System.out.println(Thread.currentThread().getName()+":"+x); } return null; } } public class MyCallableTest { public static void main(String[] args) { ExecutorService es = Executors.newFixedThreadPool( 2);//创建两个线程 //提交异步结果 Callable c = new MyCallable();//多态 es.submit(c); es.submit(c); //关闭线程池 es.shutdown(); } }
线程的常用方法
此线程开始执行 void start()
等待该线程死亡 void join()
返回此线程状态 Thread.state getState()
返回此线程的名字:Stiring getName()
返回此线程的优先级:int getPriority() 线程的优先级取值范围1-10;默认情况系统会给每个线程分配默认有限制5,线程优先级不能保证线程执行的顺序
暂停当前执行的线程,并执行其他线程static void yield()
同步机制和睡眠等待线程池
同步机制:
多线程在执行过程会抢占资源,有些线程想要修改对象,这时就需要线程同步,线程同步就是一种等待机制,多个线程形成一种等待队列,等待前面的线程使用完,下一个线程才可以使用,为了保证数据在方法中被访问时的正确性,引入了锁机制(Synchrogazed),当一个线程获得锁,独占资源,其他线程必须等待
实现案例
public class MySynchorgazed implements Runnable{
private static int tickets = 100; //100张票
private Object obj = new Object();
Demo demo = new Demo();
@Override
public void run() {
while(true){
synchronized (demo){//同步机制Synchorgazed
if(tickets>0){
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"正在出售第"+(tickets--)+"张票");
}
}
}
}
}
class Demo{}
public class MySynchorgazedTest {
public static void main(String[] args) {
MySynchorgazed msd = new MySynchorgazed();
Thread t1 = new Thread(msd,"窗口一");
Thread t2 = new Thread(msd,"窗口二");
Thread t3 = new Thread(msd,"窗口三");
t1.start();
t2.start();
t3.start();
}
}
睡眠和等待
等待wait(),让线程进入等待状态,知道被通知
notify通知,随机通知一个线程
睡眠sleep()时间毫秒,让线程睡眠一段时间,睡眠结束后自动唤醒,继续执行
二者的区别
wait()由锁对象调用,sleep()由当前线程调用。
wait()可以被其他线程通知唤醒,sleep()只能等待睡眠时间结束。
wait()等待会释放锁,sleep()不会释放锁
生产者消费者模式(唤醒机制)
例如:包子铺,老板(生产者)做一个包子递给客户(消费者),没有客户就等待不做。当多个客户来买包子得等待。
解决方案:加一个缓冲区(蒸笼)。老板可以提前做一定数量的包子放进蒸笼,不用等待客户来。客户也可以直接从蒸笼拿,不用等老板做。当蒸笼没有包子在通知老板做
资源类数据
public class Student {
private String name;
private int age;
boolean flag;
public Student() {
}
public Student(String name, int age, boolean flag) {
this.name = name;
this.age = age;
this.flag = flag;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public boolean isFlag() {
return flag;
}
生产者资源类
public class SetThread implements Runnable {
private Student s;
private int x = 0;
public SetThread(Student s) {
this.s = s;
}
@Override
public void run() {
while (true) {
synchronized (s) {
if (s.flag) {
try {
s.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
if (x % 2 == 0) {
s.setName("李四") ;
s.setAge(28);
} else {
s.setName("张三") ;
s.setAge(15);
}
x++;
s.flag=true;
s.notify();
}
}
}
}
消费者资源类
public class GetThread implements Runnable {
private Student s;
public GetThread(Student s) {
this.s = s;
}
@Override
public void run() {
while (true) {
synchronized (s) {
if (!s.flag) {
try {
s.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.print(s.getName() + " ");
System.out.print(s.getAge());
System.out.println();
s.flag = false;
s.notify();
}
}
}
}
测试类
public class Test {
public static void main(String[] args) {
Student s = new Student();
SetThread st =new SetThread(s);
GetThread gt = new GetThread(s);
Thread t1 = new Thread(st);
Thread t2 = new Thread(gt);
t1.start();
t2.start();
}
}
线程之静态代理
代理模式核心思想:代理角色帮助真实角色完成一些事情,比如买房可以找中介,过年回家买过车票,
代理角色和真实角色都要实现同一个接口
public class StaticProxy {
public static void main(String[] args) {
Mary mary = new You();
mary.mary();
You you = new You();
WeddingCompany weddingCompany =new WeddingCompany(you);
weddingCompany.mary();
}
}
interface Mary{
void mary();
}
class You implements Mary{
public void mary(){
System.out.println("我结婚了,我很开心");
}
}
class WeddingCompany implements Mary{
private Mary mary;
public WeddingCompany(Mary mary) {
this.mary = mary;
}
@Override
public void mary() {
System.out.println("婚庆公司帮忙布置婚礼现场");
mary.mary();
System.out.println("婚庆公司帮忙完成整个婚礼");
}
}