线程

xiaoxiao2021-02-28  23

一、Thread 常用的方法及性质:

 *  1.start() :启动线程并执行相应的run()方法  *  2.run():子线程要执行的代码放在run()里面  *  3.currentThread(): 静态的,点取当前的线程  *  4.getName():获取线程的名字  *  5.setName():设置线程的名字  *  6.yield():调用此方法的线程释放当前CPU的执行权  *  7.jojn():在A线程中调用B线程的此方法,表示A线程停止执行直至B执行完毕,A线程在接着执行join()之后的代码  *  8.isAlive(): 判断当前线程是否活着  *  9.sleep(long l):显示的让当前线程睡眠l毫秒  *  10.线程通信:wait(),notify(),notifyAll()  *     * 设置线程的优先级:  *  getPriority():返回线程的优先级  *  setPriority(int newPrioritty):改变线程的优先级  *    * 一个线程只能执行一次start()

 * Runnable 接口要比Thread 类更好的实现数据共享,而不是唯一。

 *  死锁:不同的线程分别占用对方需要的同步资源不放弃,都在等待对方放弃自己需要的同步资源,就形成了死锁。(处理线程同步时,容易出现)

二、多线程卖票机制

 * 线程安全问题存在的原因?  *         由于一个线程在操作共享数据过程中,未执行完毕的情况下,另外的线程参与进来,导致共享数据存在安全问题。  * 如何解决线程的安全问题?  *         必须让一个线程操作完共享数据后,其他线程才有机会参与操作共享数据。  * Java如何实现线程的安全:线程的同步机制  *         方式一:同步代码块  *             synchronized(同步监视器){  *             //需要被同步的代码块(即操作共享数据的代码)  *             }  *             1.共享数据:多个线程共同操作的同一个数据(变量)  *             2.同步监视器:由一个类的对象来充当,哪个线程获取此监视器,谁就执行大括号里面被同步的代码。俗称:锁。  *         方式二:同步方法:将操作共享数据的方法声明为synchronized。即此方法为同步方法,能够保证当其中一个线程执行此方法时  *                 其他线程在外等待直至此线程执行完该方法  *             1.同步方法的锁:this.(应当实现Runbable 接口,此时的this代表的是同一个对象)  *             2.如果是用选择继承 Thread 的话,此时不应该使用同步方法;因为同步方法的锁就是当前对象,这样对于每个继承  *                  Thread 的对象都是一个独立的锁,不能达到同步的目的。  * 线程同步的弊端:由于同一个时间只能有一个线程访问共享数据,效率变低了。

三、线程通信

/* * 线程通信:如下的三个关键字使用的话,都得在同步代码块或同步方法中。 * wait():线程的等待,一旦一个线程执行到wait(),就释放当前的锁。 * notify()/notifyAll():唤醒wait的一个或所有的线程 * * 使用两个打印1-100,线程1、2,交替打印。 */ class PrintNum implements Runnable{ int num = 1; public void run(){ while(true){ synchronized (this) { notify();//唤醒线程 if (num <= 100) { try { Thread.currentThread().sleep(10); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + ":" + num++); } else { break; } try { wait(); //等待 } catch (InterruptedException e) { e.printStackTrace(); } } } } } public class testCommunication { public static void main(String[] args) { PrintNum p1 = new PrintNum(); Thread t1 = new Thread(p1, "打印机甲"); Thread t2 = new Thread(p1, "打印机乙"); t1.start(); t2.start(); } }

四、常用案列

    1.懒汉式

     

//关于懒汉式线程安全问题:使用同步机制 //对于一般的方法内,使用同步代码块,可以考虑使用this //对于静态方法而言,使用当前本类充当锁 public class TestSingleton { public static void main(String[] args) { Singleton s1 = Singleton.getInstance(); Singleton s2 = Singleton.getInstance(); System.out.println(s1 == s2); } } class Singleton{ private Singleton(){ } private static Singleton instance = null; public static Singleton getInstance(){ if(instance == null){ synchronized (Singleton.class) { if (instance == null) { instance = new Singleton(); } } } return instance; } }

二、账户存钱

/* * 有一个银行账号,余额为0,现在有两个用户,向你们存钱,每次存1000,一共存三次,存完后,余额3000. * * 1.线程同步。 * 2.数据共享 */ class Account { double balance;// 余额 public Account() { } // 存钱 public synchronized void deposit(double amt) {//这里的锁相当于this balance += amt; try { Thread.currentThread().sleep(10); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + ":" + balance + "¥"); } } class Customer extends Thread { Account account; public Customer(Account account) { this.account = account; } public void run() { for (int i = 0; i < 3; i++) account.deposit(1000); } } public class testThread2 { public static void main(String[] args) { Account account = new Account(); //同一个对象,相当于一把锁,保证了同步问题。 Customer c1 = new Customer(account); Customer c2 = new Customer(account); c1.setName("甲"); c2.setName("乙"); c1.start(); c2.start(); } }

三、生产者和消费者问题

/* * 生产者和消费者问题: * 生产者将生产的商品交给店员,店员负责给消费者提供商品;店员的货架上最多只能存放20件商品,当放满后,应该通知生产者暂停一下 * 当货架上的商品为0时,应该告知消费者稍等一下。 * * 分析: * 1.多线程问题(生产者和消费者) * 2.涉及到共享数据,应当考虑安全 * 3.共享数据-产品的数量 * 4.涉及到线程的通信 */ class Clerk{ //店员 int produce; public synchronized void addProduce(){ if(produce >= 20){ try { wait(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } }else{ produce++; System.out.println(Thread.currentThread().getName()+" :生产了第"+produce+"件商品"); try { Thread.currentThread().sleep(1000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } notifyAll(); } } public synchronized void consumeProduce(){ if(produce <= 0){ try { wait(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } }else{ try { Thread.currentThread().sleep(1000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+" :消费第"+produce+"件商品"); produce--; notify(); } } } class Producer implements Runnable{ //生产者 Clerk clerk; public Producer(Clerk clerk) { this.clerk = clerk; } @Override public void run() { System.out.println("生产者开始生产商品:"); try { Thread.currentThread().sleep(2000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } while(true){ clerk.addProduce(); } } } class Consume implements Runnable{ Clerk clerk; public Consume(Clerk clerk){ this.clerk = clerk; } @Override public void run() { System.out.println("消费者开始消费商品:"); try { Thread.currentThread().sleep(2000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } while(true){ clerk.consumeProduce(); } } } public class testProduceConsume { public static void main(String[] args) { Clerk clerk = new Clerk(); Producer p1 = new Producer(clerk); Producer p2 = new Producer(clerk); Producer p3 = new Producer(clerk); Producer p4 = new Producer(clerk); Consume c1 = new Consume(clerk); Consume c2 = new Consume(clerk); Consume c3 = new Consume(clerk); Thread t1 = new Thread(p1, "生产者1"); Thread t2 = new Thread(p2, "生产者2"); Thread t3 = new Thread(p3, "生产者3"); Thread t4 = new Thread(p4, "生产者4"); Thread T1 = new Thread(c1, "消费者1"); Thread T2 = new Thread(c2, "消费者2"); Thread T3 = new Thread(c3, "消费者3"); t1.start(); t2.start(); t3.start(); t4.start(); T1.start(); T2.start(); T3.start(); } }

转载请注明原文地址: https://www.6miu.com/read-1400178.html

最新回复(0)