Java多线程

线程一些简单词语

Thread()

Priority 优先级

Join 强制执行

Run  方法只有一条执行路径

Sleep 线程休眠

Start 线程启动 多条执行路径,主线程与子线程并行交替执行

Yield 线程礼让

主线程

Main()即为主线程入口产生其他子线程的线程必须最后完成执行,因为他执行各种关闭操作

创建线程的两种方式:

1.继承Thread类创建线程(编写简单,可直接操作   适用于单继承)

       定义MyTread类继承Thread类

       重写run()方法,编写线程执行体

       创建线程对象,调用start()方法启动线程

2. 定义MyRunnable类实现Runnable接口(避免单继承局限性,  便于共享资源)

           实现run()方法,编写线程执行体

           创建线程对象,调用Start()方法启动线程

线程的五种状态:创建(启动线程)       就绪          阻塞           运行             死亡

线程调度(按照特定机制为多个线程分配CPU使用权)

SetPriority(int newPriority)     更改线程的优先级

Static void sleep(long millis)在指定的毫秒数内让当前正在执行的线程休眠

Void join() 等待该线程终止

Static void yield ()   暂停当前正在执行的线程对象,并执行其他线程

Void interrupt () 中断线程

Boolean isAlive() 测试线程是否处于活动状态

     SetPriority(int newPriority)       线程优先级 1级最小 默认5级   优先级高的获得CPU资源概率较大

 

让线程暂时睡眠指定时长,线程进入阻塞状态

睡眠时间过后线程会在进入可运行状态

Static void sleep(long millis)millis为休眠时长,以毫秒为单位,调用sleep 方法需要处理

interruptedException 异常

 

线程的强制运行

当前线程暂停执行,等待其他线程结束后在继续执行次线程

Public final void join(

Public final void join(long mills

Public final void join(long mills,int nanos

Millis 以毫秒为单位的等待时长

Nanos 要等待的附加纳秒时长

需处理interruptedException异常

线程的礼让

暂停当前线程,允许其他具有相同优先级的线程获得运行机会

该线程处于就绪状态,不转为阻塞状态

Static void yield () 只是提供一种可能,但是不能保证一定会实现礼让

 

线程的同步

多线程实现网络购票,用户提交购票后

1.网站修改网站车票数据2.显示出票反馈信息给用户

 

线程不安全问题

当多个线程共享同一个资源时,一个线程未完成全部操作的时候,其他线程修改数据,造成数据不安全问题

 

同步方法

使用Synchronized修饰的方法控制对类成员变量的访问

访问修饰符synchronized返回类型方法名(参数列表){....}

Synchronized访问修饰符 返回类型方法名(参数列表){....}

 

Synchronized就是为当前的线程声明一把锁

同步代码块

使用synchronized关键字修饰的代码块

Synchronized(synObject){

//需要同步的代码块

}

synObject为需要同步的对象,通常为this

 

多个并发线程访问同一资源的同步代码块时

  1. 同一时刻只能有一个线程进入synchronized(this)同步代码块
  2. 当一个线程访问一个synchronized(this)同步代码块时,其他synchronized(this)同步代码块同样被锁定
  3. 当一个线程访问一个synchronized(this)同步代码块时,其他线程可以访问该资源的非synchronized(this)同步代码

 

线程安全类型

               方法是否同步             效率比较               适合场景

线程安全          是                        低               多线程并发共享资源

非线程安全         否                     高                     单线程

 

并行:多个cpu实例或者多台机器同时执行一段处理逻辑,是真正的同时。

并发:通过cpu调度算法,让用户看上去同时执行,实际上从cpu操作层面不是真正的同时。并发往往在场景中有公用的资源,那么针对这个公用的资源往往产生瓶颈,我们会用TPS或者QPS来反应这个系统的处理能力。

线程安全:经常用来描绘一段代码。指在并发的情况之下,该代码经过多线程使用,线程的调度顺序不影响任何结果。这个时候使用多线程,我们只需要关注系统的内存,cpu是不是够用即可。反过来,线程不安全就意味着线程的调度顺序会影响最终结果.

       同步:Java中的同步指的是通过人为的控制和调度,保证共享资源的多线程访问成为线程安全,来保证结果的准确。

Hashtable  && HashMap

 

Hashtable

继承关系 实现Map接口,继承Dictionary类

线程安全,效率低

键和值都不允许为null

HashMap

继承关系 实现Map接口,继承AbstractMap类

        非线程安全,效率高

         键和值都允许为null

StringBuffer && StringBuilder

前者线程安全后者非线程安全

 

为什么要进行线程同步:当多个线程去操作同一份共享资源时避免出现数据不一致

死锁

产生原因:当两个线程都在等待对方先完成,造成程序的停滞

条件: 两个或两个以上的线程在活动       某个线程拿到一个锁以后还想那第二个锁,造成锁的嵌套

避免:某一个线程首先释放他的锁

      尽量减少同步方法或同步代码块嵌套

&&生产者和消费者问题

需要Object方法

电影类

public class Movie {
    private String name ;
    private String info;
    private boolean flag=true;//控制生产者生产
    public String getName() {
        return name;
    }
    public String getInfo() {
        return info;
    }
    public synchronized void get(){
        if(flag){
            try {
                super.wait();
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
         System.out.println(this.getName()+"-"+this.getInfo());
         flag=true;
         super.notify();
    }
    
    
    public synchronized void set(String name,String info){
        if(!flag){
            try {
                super.wait();
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        this.name=name;
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        this.info=info;
        flag=false;
        super.notify();
    }
    
}
 

 

客户类
public class Customer implements Runnable {                  
     private Movie movie=null;
     
     public Customer(Movie movie) {
        super();
        this.movie = movie;
    }

    public void run(){
         for(int i=0;i<50;i++){
             try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }         
             this.movie.get();

         }
     }
}
生产者类

public class Producter implements Runnable{
    private Movie movie=null;
    private Boolean flag=false;
    
    public Producter(Movie movie) {
        super();
        this.movie = movie;
    }

    public void run(){
        //录入电影数据
        for(int i=0;i<50;i++){
            if(flag){
                
                this.movie.set("变形金刚","一部科幻电影");
                flag=false;
            }else{
                this.movie.set("神偷奶爸","一部3D电影");
                flag=true;
            }
        }
        
        
    }
    
}

测试类

public class Test {

    public static void main(String[] args) {
         Movie movie=new Movie();
         Thread producter=new Thread(new Producter(movie));
         Thread customer =new Thread(new Customer(movie));
         producter.start();
         customer.start();
    }

}
 

 

线程池

线程缺乏统一管理,占用过多内存

缺乏更多功能,如定时执行,定期执行

使用线程池好处:

重用存在的线程,减少对象创建,消亡的开端

有效控制最大并发数,提高系统资源使用率

定时执行,定期执行

顶级父类:Excute

线程池所在包java.util.concurrent

顶级接口是Excutor,真正的线程池接口是excutorService

java.util.concurrent Executors类提供创建线程池的方法

//使用newFixedThreadPool()方法创建线程池
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class Test {
	public static void main(String[] args) {
		ExecutorService cachedThreadPool=Executors.newFixedThreadPool(3);
		for(int i=0;i<10;i++){
			cachedThreadPool.execute(new MyRunnable(i));
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	
	
	
	}
}

class MyRunnable implements Runnable{
	int num;
	public MyRunnable(int num) {
	super();
	this.num = num;
    }
	public void run(){
		System.out.println(Thread.currentThread().getName()+":"+num);
	
}
}
//使用线程池创建任务
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class Test {
	public static void main(String[] args) {
		ExecutorService cachedThreadPool=Executors.newCachedThreadPool();
		for(int i=0;i<10;i++){
			cachedThreadPool.execute(new MyRunnable(i));
			try {
				Thread.sleep(200);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	
	
	
	}
}

class MyRunnable implements Runnable{
	int num;
	public MyRunnable(int num) {
	super();
	this.num = num;
    }
	public void run(){
		System.out.println(Thread.currentThread().getName()+":"+num);
	
}
}

 

 

 

你可能感兴趣的:(Java多线程)