JavaSE基础---多线程

Posted 猪八戒1.0

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JavaSE基础---多线程相关的知识,希望对你有一定的参考价值。

 

 一:进程的概念

 

只有一个CPU,是怎么同时运行程序的呢?

把CPU的执行时间分成很多小块,每小块的时间都是固定的,把一个小块叫做时间片,时间片的时间可以非常短

二:创建多线程

 

 

(1)继承Thread 

         1.线程不能重复启动,否则会报错,主函数也是一个线程,会先执行主函数的线程再执行其他线程。调用start()方法即会执行run()方法。

测试:

//只能有一个public类,故未加public
class MyThread extends Thread
    public void run()
        //由于继承了Thread类,可以不通过对象直接调用getName()方法
        System.out.println(getName()+"该线程被执行");
    


public class TestThread 
    public static void main(String[] args) 
        MyThread mt=new MyThread();
        mt.start();//启动线程
        System.out.println("主线程");
    

运行结果:

         2.线程获取CPU的使用权是随机的,每次运行结果会不同

测试:


class MyThread extends Thread
    public MyThread(String name)
        //调用父类Thread的构造函数
        super(name);
    
    public void run()
        for (int i = 1; i <=5 ; i++) 
            System.out.println(getName()+"正在运行"+i);
        
    


public class TestThread 
    public static void main(String[] args) 
        MyThread mt1=new MyThread("进程1");
        MyThread mt2=new MyThread("进程2");
        mt1.start();//启动线程
        mt2.start();
    

运行结果:

(2)Runnable接口

         extends 是继承父类,只要那个类不是声明final或者定义为abstract就能继承,Java中不支持多重继承,继承只能继承一个类,但implements可以实现多个接口,用逗号分开就行了。由于Runnable是接口,故用implements在其前。构建的类PrintRunnable创建的对象没有start()方法,需要通过Thread类创建对象。

 测试:



class PrintRunnable implements Runnable

    public void run()
        for (int i = 1; i <=5 ; i++) 
            System.out.println(Thread.currentThread().getName()+"正在运行"+i);
        
    


public class TestRunnable 
    public static void main(String[] args) 
        PrintRunnable pr1=new PrintRunnable();
        PrintRunnable pr2=new PrintRunnable();
        Thread t1=new Thread(pr1);
        Thread t2=new Thread(pr2);
        t1.start();
        t2.start();
    

        Thread-0、Thread-1是系统自定义的线程名 

运行结果:

三:线程的生命周期

join抢先执行 ,不使用原本随机执行

 测试


class MyThread extends Thread
    public void run()
        for (int i = 1; i <=5 ; i++) 
            System.out.println(getName()+"正在执行"+i+"次!");
        


public class TestJoin 
    public static void main(String[] args) 
        MyThread mt=new MyThread();
        mt.start();
        //不抛出或者使用try carch 报错
        try 
            mt.join();
         catch (InterruptedException e) 
            e.printStackTrace();
        
        for (int i = 1; i <5 ; i++) 
            System.out.println("主进程正在执行"+i+"次!");
        
    

运行

实际上使用Sleep对应休眠时间之后,是处于可运行阶段再去获取CPU资源,实际上的时间是大于休眠的时间的 。当两个对象时,运行结果交替运行的概率比较大,由于一个对象执行方法后休眠,此时另一个对象获取CPU资源的概率比较大。

 测试1

sleep(1000) 每次执行隔1000ms

class MyThread implements Runnable
    public void run()
        for (int i = 1; i <=5 ; i++) 
            try 
                Thread.sleep(1000);
             catch (InterruptedException e) 
                e.printStackTrace();
            
            System.out.println(Thread.currentThread().getName()+"正在执行"+i+"次!");
        
    

public class TestSleep 
    public static void main(String[] args) 
        MyThread mt=new MyThread();
        Thread t=new Thread(mt);
        t.start();
        System.out.println("主进程执行");
        
    

 运行:

测试2 

class MyThread implements Runnable
    public void run()
        for (int i = 1; i <=5 ; i++) 
            try 
                Thread.sleep(1000);
             catch (InterruptedException e) 
                e.printStackTrace();
            
            System.out.println(Thread.currentThread().getName()+"正在执行"+i+"次!");
        
    

public class TestSleep 
    public static void main(String[] args) 
        MyThread mt=new MyThread();
        Thread t1=new Thread(mt);
        t1.start();
        Thread t2=new Thread(mt);
        t2.start();
    

运行:

 

 

        线程优先级的设置与操作系统的环境以及CPU的调度方式都是有关系的,所以结果不能完全把握优先级高的线程一定先执行,运行结果还是具有随机性的

测试:


class MyThread extends Thread
    private String name;
    public MyThread(String name)
        this.name=name;
    
    public void run()
        for (int i = 1; i <=5 ; i++) 
            System.out.println(name+"正在执行"+i+"次!");
        
    

public class TestSleep 
    public static void main(String[] args) 
        int mainPriority=Thread.currentThread().getPriority();
        System.out.println("主函数的优先级是"+mainPriority);

        MyThread mt=new MyThread("线程1");
        mt.setPriority(Thread.MAX_PRIORITY);
        //等价 mt.setPriority(10);
        mt.start();

        System.out.println("线程1的优先级是"+mt.getPriority());

    

运行:

四.线程同步 

 

        同步的关键字可以确保对象共享,共享对象在同一时刻只能被一个线程访问。可以称做线程同步或者线程互斥

 

 五.线程间通信

 

 

        有生产后才能消费,若一生产一消费,由于线程运行的随机性,会出现没有生产时消费的情况,需要配合进程同步,wait(),notifyAll()等方法解决

测试:

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();
	
	

Producer类 

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();
			
		
		
	


Consumer类 

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();
			
		
	
	

开发者涨薪指南 48位大咖的思考法则、工作方式、逻辑体系

以上是关于JavaSE基础---多线程的主要内容,如果未能解决你的问题,请参考以下文章

JAVASE02-Unit010: 多线程基础 TCP通信

JavaSE8基础 多线程setDaemon 守护线程

JavaSE8基础 多线程join 线程加入

JavaSE8基础 多线程interrupt 线程中断

JavaSE基础---多线程

[javaSE] 多线程通信(等待-唤醒机制)