多线程创建编程

多线程

前言

在这里插入图片描述

线程相当于一个子程序,一个进程包含多个线程


线程的创建

  • 创建Thread类
  • 实现Runnable接口
    Thread
    Thread方法
    Runnable

线程创建

package day5;

class MyThread extends Thread{
    public void run(){
        System.out.println(getName()+"MyThread 正在执行!");
    }
}
public class ThreadTest {
    public static void main(String[] args) {
        //System.out.println("主线程1");
        MyThread mt=new MyThread();
        mt.start(); // 启动线程,自动执行run方法
        //System.out.println("主线程2"); // 先输出主线程代码

    }
}

package day5;

class MyThread extends Thread{
    public MyThread(String name){
        super(name);
    }
    public void run(){
        for (int i=1;i<11;i++){
            System.out.println(getName()+"正在运行"+i+"次");
        }
    }
}
public class ThreadTest {
    public static void main(String[] args) {
        MyThread mt=new MyThread("线程1");
        MyThread mt2=new MyThread("线程2");
        // 线程执行是随机执行,每次顺序不同
        mt.start();
        mt2.start();
    }
}

  • Runnable
  • 为什么要实现Runnalble接口?
    • Java不支持多继承
    • 不打算重写Thread类的其他方法
package day5;

class PrintRunnable implements Runnable{
    @Override
    public void run() {
        int i = 1;
        while (i <= 10) {
            System.out.println(Thread.currentThread().getName() + " 正在运行!"+i++);
        }
    }
}
public class Test {
    public static void main(String[] args) {
        PrintRunnable pr=new PrintRunnable();
        // 启动Runnable线程,运行依旧有随机性
        Thread t1=new Thread(pr);
        t1.start();
        PrintRunnable pr2=new PrintRunnable();
        // 启动Runnable线程
        Thread t2=new Thread(pr2);
        t2.start();
    }
}

package day5;

class PrintRunnable implements Runnable{
    int i = 1;
    @Override
    public void run() {
        while (i <= 10) {
            System.out.println(Thread.currentThread().getName() + " 正在运行!"+i++);
        }
    }
}
public class Test {
    public static void main(String[] args) {
        PrintRunnable pr=new PrintRunnable();
        // pr 被多线程共享
        Thread t1=new Thread(pr);
        t1.start();
        Thread t2=new Thread(pr);
        t2.start();
    }
}

在这里插入图片描述

线程状态

  • 新建(New)
  • 可运行( Runnable )
  • 正在运行( Running )
  • 阻塞( Blocked )
    线程的生命周期

sleep方法应用

  • Thread类的方法

public static void sleep(long millis)

  • 作用:在指定的毫秒数内让正在执行的线程休眠(暂停执行)
package day5;

class PrintRunnable implements Runnable{
    int i = 1;
    @Override
    public void run() {
        while (i <= 15) {
            System.out.println(Thread.currentThread().getName() + " 正在运行!"+i++);
            try {
                // 1000ms 休眠,实际时间比1000更多
                Thread.sleep(1000);
            }catch (InterruptedException e){
            // 会发生中断异常所以需要捕获
                e.printStackTrace();
            }

        }
    }
}
public class Test {
    public static void main(String[] args) {
        PrintRunnable pr=new PrintRunnable();
        Thread t1=new Thread(pr);
        t1.start();
        Thread t2=new Thread(pr);
        t2.start();
    }
}


join方法应用

  • Thread类的方法

public final void join()

  • 作用:等待调用该方法的线程结束后才能执行,抢占线程优先
package day5;

class MyThread extends Thread {
    public MyThread(String name) {
        super(name);
    }

    public void run() {
        for (int i = 0; i <=20 ; i++) {
            System.out.println(getName() + "正在运行"+i);
        }
    }
}

public class ThreadTest {
    public static void main(String[] args) {
        MyThread mt = new MyThread("线程1");
        // 线程执行是随机执行,每次顺序不同
        mt.start();
        try{
            // 抢占资源先运行
            mt.join();
        }catch (InterruptedException e){
            e.printStackTrace();
        }
        for (int i = 0; i <=20; i++) {
            System.out.println("主线程结束"+i);
        }
    }
}

  • Thread类的方法

public final void join(long millis)

  • 作用:等待该线程终止的最长时间为millis毫秒。

线程优先级

  • Java为线程类提供了10个优先级

  • 优先级可以用整数1-10表示,超过范围会抛出异常

  • 主线程默认优先级为5(数越大优先级越高)

  • 优先级常量

    • MAX_ PRIORITY :线程的最高优先级10
    • MIN_ PRIORITY :线程的最低优先级1
    • NORM_ PRIORITY :线程的默认优先级5
  • 优先级相关的方法

public int getPriority() 获取线程优先级的方法
public void setPriority(int newPriority) 设置线程优先级的方法

package day5;

class MyThread extends Thread {
    private String name;

    public MyThread(String name) {
        this.name = name;
    }

    public void run() {
        for (int i = 0; i <= 10; i++) {
            System.out.println("线程" + name + "正在运行" + i);
        }
    }
}

public class ThreadTest {
    public static void main(String[] args) {
        // 获取主线程的优先级
//        System.out.println("主线程:"+Thread.currentThread().getPriority());

        MyThread mt = new MyThread("线程1");
        MyThread mt2 = new MyThread("线程2");
        // mt.setPriority(10);与下方语句等价 不同环境运行方式不同
        mt.setPriority(Thread.MAX_PRIORITY);
        mt2.setPriority(Thread.MIN_PRIORITY);
        mt.start();
        mt2.start();

    }
}


线程同步

  • 多线程运行问题
    • 各个线程是通过竞争CPU时间而获得运行机会的
    • 各线程什么时候得到CPU时间,占用多久,是不可预测的
    • 一个正在运行着的线程在什么地方被暂停是不确定的
  • 银行存取款问题
    • 为了保证在存款或取款的时候,不允许其他线程对帐户余额进
      行操作
    • 需要将Bank对象进行锁定
    • 使用关键字synchronized实现
    • synchronized关键字用在
      • 成员方法
      • 静态方法
      • 语句块
      • public synchronized void saveAccount({}
      • public static synchronized void saveAccount({}
      • synchronized (obi){… .}
  • 例题:银行家
    • Bnak类
package day8.bank;

public class Bank {
	private String account;// 账号
	private int balance;// 账户余额

	public Bank(String account, int balance) {
		this.account = account;
		this.balance = balance;
	}

	public String getAccount() {
		return account;
	}

	public void setAccount(String account) {
		this.account = account;
	}

	public int getBalance() {
		return balance;
	}

	public void setBalance(int balance) {
		this.balance = balance;
	}

	@Override
	public String toString() {
		return "Bank [账号:" + account + ", 余额:" + balance + "]";
	}

	// 存款
	public synchronized void saveAccount() {

		// 获取当前的账号余额
		int balance = getBalance();
		try {
			// 测试添加延迟 
			Thread.sleep(1000);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		// 修改余额,存100元
		balance += 100;
		// 修改账户余额
		setBalance(balance);
		// 输出存款后的账户余额
		System.out.println("存款后的账户余额为:" + balance);
	}

	public void drawAccount() {
		synchronized (this) {
			// 在不同的位置处添加sleep方法

			// 获得当前的帐户余额
			int balance = getBalance();
			// 修改余额,取200
			balance = balance - 200;
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			// 修改帐户余额
			setBalance(balance);
			System.out.println("取款后的帐户余额:" + balance);
		}

	}
}

- DrawAccount类
package day8.bank;
//取款
public class DrawAccount implements Runnable{
	Bank bank;
	public DrawAccount(Bank bank){
		this.bank=bank;
	}
	@Override
	public void run() {
		bank.drawAccount();
	}
	
}

- SvaeAccount类
package day8.bank;
//存款
public class SaveAccount implements Runnable{
	Bank bank;
	public SaveAccount(Bank bank){
		this.bank=bank;
	}
	@Override
	public void run(){
		bank.saveAccount();
	}
}

- main 测试类
package day8.bank;

public class Test {

	public static void main(String[] args) {
		// 创建帐户,给定余额为1000
		Bank bank=new Bank("1001",1000);
		//创建线程对象
		SaveAccount sa=new SaveAccount(bank);
		DrawAccount da=new DrawAccount(bank);
		Thread save=new Thread(sa);
		Thread draw=new Thread(da);
		save.start();
		draw.start();
		try {
			
			draw.join();
			save.join();
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		System.out.println(bank);
	}

}

线程间通信

在这里插入图片描述

  • 例题:生产者与消费者
    • Queue
package day8.queue;

public class Queue {
	private int n;
	boolean flag=false;
	
	public synchronized int get() {
		if(!flag){
			try {
			// 执行等待
				wait();
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		System.out.println("消费:"+n);
		flag=false;//消费完毕,容器中没有数据
		notifyAll();
		return n;
	}

	public synchronized void set(int n) {
		if(flag){
			try {
				wait();
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		System.out.println("生产:"+n);
		this.n = n;
		flag=true;//生产完毕,容器中已经有数据
		notifyAll();
	}
	
}

  • Consumer
package day8.queue;

public class Consumer implements Runnable{
	Queue queue;
	Consumer(Queue queue){
		this.queue=queue;
	}

	@Override
	public void run() {
		while(true){
			queue.get();
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
	
}

  • Producer
package day8.queue;

public class Producer implements Runnable{
	Queue queue;
	Producer(Queue queue){
		this.queue=queue;
	}

	@Override
	public void run() {
		int i=0;
		while(true){
			queue.set(i++);
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		
	}

}

  • main
package day8.queue;

public class Test {

    public static void main(String[] args) {
        Queue queue = new Queue();
        new Thread(new Producer(queue)).start();
        new Thread(new Consumer(queue)).start();
    }

}

  • wait(方法:中断方法的执行,使线程等待
  • notify0方法:唤醒处于等待的某一个线程 ,使其结束等待
  • notifyAll()方法:唤醒所有处于等待的线程,使它们结束等待
  • 用于解决死锁

创建多线程的第三种方式

请添加图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值