• Java多线程应用总结


    一、基本方法


    进程和线程一样,都是实现并发的一个基本单位。线程是比进程更小的执行单位,线程是在进程的基础上进行的进一步划分。所谓多线程,是指一个进程在执行过程中可以产生多个更小的程序单元,这些更小的单元称为线程,这些线程可以同时存在、同时运行。

    Tread类中的主要方法:

    序  号 方法名称 类  型 描  述
    1 public Thread(Runnable target) 构造 接收Runnable接口子类对象,实例化Thread对象
    2 public Thread(Runnable target, String name) 构造 接收Runnable接口子类对象,实例化Thread对象,并设置线程名称
    3 public Thread(String name) 构造 接收Runnable接口子类对象,并设置线程名称
    4 public static Thread currentThread() 普通 返回目前正在执行的线程
    5 public final String getName() 普通 返回线程的名称
    6 public final int getPriority() 普通 返回线程的优先级
    7 public boolean isInterrupted() 普通 判断目前线程是否被中断,如果是返回true,否则返回false
    8 public final boolean isAlive() 普通 判断线程是否在活动,如果是返回true,否则返回false
    9 public final void join() throws Interrupted Exception 普通 等待线程死亡
    10 public final synchronized void join(long millis) throws Interrupted Exception 普通 等待millis毫秒后,线程死亡
    11 public void run() 普通 执行线程
    12  public final void setName(String name) 普通 设定线程名称
    13 public final void setPriority(int newPriority ) 普通 设定线程的优先级
    14 public static void sleep(long millis) throws InterruptedException 普通 使目前正在执行的线程休眠millis毫秒
    15 public void start() 普通 开始执行线程
    16 public String toString() 普通 返回代表线程的字符串
    17 public static void yield() 普通 将目前正在执行的线程暂停,允许其他的线程执行
    18 public final void setDaemon(boolean on) 普通 将一个线程设置成后台运行

     二、多线程的实现方式及其异同

    方式一:

    package test.thread.share.first;
    
    class MyThread extends Thread {
    	private int ticket = 5;
    	public void run(){
    		for(int i = 0; i<10; i++)
    			if(ticket > 0){
    				System.out.println("买票: ticket =" + ticket--);
    			}
    	}
    }
    public class ThreadShare {
    
    	public static void main(String[] args) {
    		MyThread mt1 = new MyThread();
    		MyThread mt2 = new MyThread();
    		MyThread mt3 = new MyThread();
    		mt1.start();
    		mt2.start();
    		mt3.start();
    	}
    }
    

    方式二:

    package test.thread.share.second;
    
    class MyThread implements Runnable{
    	private int ticket = 5;
    	public void run(){
    		for(int i=0; i<10; i++){
    			if(ticket > 0){
    				System.out.println("买票 ticket = " + ticket--);
    			}
    		}
    	}
    }
    public class ThreadShare {
    
    	public static void main(String[] args) {
    		new Thread(new MyThread()).start();
    		new Thread(new MyThread()).start();
    		new Thread(new MyThread()).start();
    	}
    }
    

    方式三:

    在方式二的基础上略微改动一下。

    package test.thread.share.second;
    
    class MyThread implements Runnable{
    	private int ticket = 5;
    	public void run(){
    		for(int i=0; i<10; i++){
    			if(ticket > 0){
    				System.out.println("买票 ticket = " + ticket--);
    			}
    		}
    	}
    }
    public class ThreadShare {
    
    	public static void main(String[] args) {
    //		new Thread(new MyThread()).start();
    //		new Thread(new MyThread()).start();
    //		new Thread(new MyThread()).start();
    		MyThread my = new MyThread();
    		new Thread(my).start();
    		new Thread(my).start();
    		new Thread(my).start();
    	}
    }
    

     方式一与方式二本质上没有什么差别,但是方式三却实现了真正的资源共享,其关键在于Thread类的不同构造方式,new Thread(); 与 new Tread(Runnable target); 这两种方式最终是要调用start()方法,而start()方法是在调用run()方法。因此,关键取决于所调用的run()方法。只有采用new Tread(Runnable target); 这种方式才有可能让传入的参数引用指向同一个run()方法的地址引用,这种机制本质上由于Runnable接口没有定义start()方法,而Thread()构造函数(也可以包含参数)或者说Thread类的内在能力仍然是开辟新的线程任务(引用),一视同仁,至于传入的是什么它不管,只要合法就行,只要最终可以正确的引用到run()方法就Ok了。

    三 关于join()

    我个人的理解是让当前的线程任务保持join,也就是在一起,不可分割,一次执行完。有点类似于synchronized()的功能,但是synchronized()的参数不能为static object。

    public static void main(String[] args) {
    		MyThread mt = new MyThread();
    		Thread t = new Thread(mt, "线程");
    		t.start();
    		for(int i=0; i<50; i++){
    			if(i>10){
    				try{
    					t.join();
    				} catch(Exception e){	
    				}
    				System.out.println("Main 线程运行 ---> " + i);
    			}
    		}
    	}
    

      上面这段代码中,t线程执行完后,才轮到Main 线程执行,且for循环一次执行完,中间不会穿插着t线程的任务。正常情况下,如果不采用join()方法的话,那么JVM会让t线程与main线程交替随机执行(并行执行)。

    四、等待与唤醒

    在生产者与消费者模式中会用到同步机制与等待唤醒机制,前者主要针对于局部,而后者更多的是关注整体的布局与策略。二者的配合可以让生产者与消费者模式稳健的运作。

    class Info {
    	private String name = "张三";
    	private String content = "管理员";
    	private boolean flag = false;
    	
    	public synchronized void set(String name, String content){
    		if(!flag){
    			try{
    				super.wait();
    			} catch(InterruptedException ex){
    				ex.printStackTrace();
    			}
    		}
    		this.setName(name);
    		try{
    			Thread.sleep(300);
    		} catch(InterruptedException ex){
    			ex.printStackTrace();
    		}
    		this.setContent(content);
    		flag = false;
    		super.notify();
    	}
    	
    	public synchronized void get(){
    		if(flag){
    			try{
    				super.wait();
    			} catch(InterruptedException ex){
    				ex.printStackTrace();
    			}
    		}
    		try{
    			Thread.sleep(300);
    		} catch(InterruptedException ex){
    			ex.printStackTrace();
    		}
    		System.out.println(this.getName() + "-->" + this.getContent());
    		flag = true;
    		super.notify();
    	}
    	
    	
    	public String getName(){
    		return name;
    	}
    	public void setName(String name){
    		this.name = name;
    	}
    	public String getContent(){
    		return content;
    	}
    	public void setContent(String content){
    		this.content = content;
    	}
    }

    super.notify()的含义是调用Object类的静态方法notify方法,它会唤醒第一个等待的线程执行,而notifyAll()会唤醒所有的等待线程。wait()方法会让当前执行的线程进入到等待状态,也可以理解为休眠状态。

  • 相关阅读:
    TSQL Challenge 1
    CTE的使用
    编号问题
    C语言结构体(sizeof长度)偏移量的简单研究
    【更新中】树的遍历
    【更新中】C语言语法汇总(仅记录遇到的坑)
    windows修改PowerShell(命令提示符)默认中文编码方式
    “人工智能”并不可怕
    学习《操作系统》收获
    人类大脑只开发了10%? I don't think so.
  • 原文地址:https://www.cnblogs.com/ioveNature/p/6688137.html
Copyright © 2020-2023  润新知