黑马程序员——Java(多线程)

------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------

1)进程:
是一个正在执行中的程序。
每一个进程执行都有一个执行顺序,该顺序是一个执行路径,或者叫一个控制单元。

(2)线程:
就是进程中的一个独立的控制单元。
线程在控制着进程的执行。一个进程中至少有一个线程。

java中体现:java JVM启动的时候,会有一个进程java.exe。该进程中至少有一个线程在负责java程序的执行。

(3)多线程

        java虚拟机启动的时候会有一个java.exe的执行程序,也就是一个进程。该进程中至少有一个线程负责java程序的执行。而且这个线程运行的代码存在于main方法中。该线程称之为主线程。JVM启动除了执行一个主线程,还有负责垃圾回收机制的线程。像种在一个进程中有多个线程执行的方式,就叫做多线程。

(4)多线程的利与弊:

                  好处:多线程解决了多部分同时运行的问题。

                  坏处:线程太多,执行效率太低。

(3)如何创建多线程:

                    如何实现多线程:首先,我们必须指明这个线程所要执行的代码,而这就是在Java中实现多线程我们所需要做的一切!

                       方法(1):继承 Thread 类,重写  方法 run(),我们在创建Thread 类的子类中重写 run() ,加入线程所要执行的代码即可。

               实例:

                      

 <pre name="code" class="java">class  Demo extends Thread
{
	public void run()
    {
		for(int i=1;i<10;i++)
		{
           System.out.println("Hello World!");
		}
	
	}
	public static void main(String[] args) 
	{
		Demo t=new Demo();
		t.start();
        for(int i=1;i<10;i++)
		{
			System.out.println("Hello ......World2!");
		}
	}
}


示例(2)实现runnable接口:

                        (1)定义实现Runnable接口。

                        (2)覆盖run方法,将线程的任务代码都封装在run方法中。

                        (3)通过Thread类创建线程对象,并将runnable接口的子类对象作为thread类构造函数的参数进行传递。

                                 
(4)调用start方法开启线程。 

package 练习2;

public class ThreadDemo {
	public static void main(String[]args){
		   Demo1 d=new Demo1();
		   Thread t1=new Thread(d);
		   Thread t2=new Thread(d);
		   t1.start();
		   t2.start();
	   }
}
class Demo1 implements Runnable
{
	public void run()
	{
		for(int i=0;i<20;i++)
		{
			System.out.println(Thread.currentThread().getName()+"...."+i);
		}
	}
}



二、两种方式的区别和线程的几种状态

1、两种创建方式的区别

        继承Thread:线程代码存放在Thread子类run方法中。

        实现Runnable:线程代码存放在接口子类run方法中。   

实例(1)使用继承thread类设计售票系统: 

package 多线程;
/**
 *  题目:继承thread类实现售票系统:
 *  
 *  分析:1、首先继承thread类。
 *      2、重写run方法并打印票数;
 *      3、启动多线程;
 * 
 * */
public class ThreadDemo {

	public static void main(String[] args) {
		// TODO 自动生成的方法存根
       Ticket windows1=new Ticket();
       Ticket windows2=new Ticket();
       windows1.start();
       windows2.start();
	}

}

class Ticket extends Thread
{
	private int ticket =100;
	//private String name;
	public Ticket(){}
	public void run()
	{
		while(ticket>0)
		{
			if(ticket>0)
			System.out.println(Thread.currentThread().getName()+"   "+ticket--);
		}
	}
}

  实例二:通过实现Runnable接口实现售票系统:

public class ThreadDemo {

	public static void main(String[] args) {
		// TODO 自动生成的方法存根
		Ticket t =new Ticket();
      Thread windows1=new Thread(t);
      Thread windows2=new Thread(t);
       windows1.start();
       windows2.start();
	}

}

class Ticket extends Thread
{
	private int ticket =100;
	//private String name;
	public Ticket(){}
	public void run()
	{
		while(ticket>0)
		{
			if(ticket>0)
			System.out.println(Thread.currentThread().getName()+"   "+ticket--);
		}
	}
}


2、几种状态

        被创建:等待启动,调用start启动。

         运行状态:具有执行资格和执行权。

         临时状态(阻塞):有执行资格,但是没有执行权。

         冻结状态:遇到sleeptime)方法和wait()方法时,失去执行资格和执行权,sleep方法时间到或者调用notify()方法时,获得执行资格,变为临时状态。

         消忙状态:stop()方法,或者run方法结束。

注:当已经从创建状态到了运行状态,再次调用start()方法时,就失去意义了,java运行时会提示线程状态异常


三、两种方式的区别和线程的几种状态

1、两种创建方式的区别

        继承Thread:线程代码存放在Thread子类run方法中。

        实现Runnable:线程代码存放在接口子类run方法中。      

2、几种状态

        被创建:等待启动,调用start启动。

         运行状态:具有执行资格和执行权。

         临时状态(阻塞):有执行资格,但是没有执行权。

         冻结状态:遇到sleeptime)方法和wait()方法时,失去执行资格和执行权,sleep方法时间到或者调用notify()方法时,获得执行资格,变为临时状态。

         消忙状态:stop()方法,或者run方法结束。

注:当已经从创建状态到了运行状态,再次调用start()方法时,就失去意义了,java运行时会提示线程状态异常


四、线程安全问题

1、导致安全问题的出现的原因:

        当多条语句在操作同一线程共享数据时,一个线程对多条语句只执行了一部分,还没用执行完,另一个线程参与进来执行。导致共享数据的错误。

简单的说就两点:

        a、多个线程访问出现延迟。

        b、线程随机性    

注:线程安全问题在理想状态下,不容易出现,但一旦出现对软件的影响是非常大的。

2、解决办法——同步

        对多条操作共享数据的语句,只能让一个线程都执行完。在执行过程中,其他线程不可以参与执行。

        在java中对于多线程的安全问题提供了专业的解决方式——synchronized(同步)

        这里也有两种解决方式,一种是同步代码块,还有就是同步函数。都是利用关键字synchronized来实现。

         a、同步代码块

        用法:

                  synchronized(对象)

                  {需要被同步的代码}

五:同步线程:

概述:当一个多线程应用程序同时执行多个任务时,这些任务需要同信和同步,这时会出现线程冲突的问题,所以这时就需要解决线程的同步问题。

(实例一)有同步的代码块:售票系统:

public class ThreadDemo {

	public static void main(String[] args) {
		// TODO 自动生成的方法存根
		Ticket t =new Ticket();
      Thread windows1=new Thread(t);
      Thread windows2=new Thread(t);
       windows1.start();
       windows2.start();
	}

}

class Ticket extends Thread
{
	private int ticket =100;
	//private String name;
	public Ticket(){}
	public void run()
	{
		while(ticket>=1)
			synchronized(this){
		try{
			Thread.sleep(100);
		}catch (InterruptedException e)
		{
			e.printStackTrace();
		}
			if(ticket>0)
			System.out.println(Thread.currentThread().getName()+"   "+ticket--);
		}
	}
}


六、死锁

        当同步中嵌套同步时,就有可能出现死锁现象。

实例(1)死锁:

class LockTest implements Runnable  
{  
    private boolean flag;  
    LockTest(boolean flag)  
    {  
        this.flag=flag;  
    }  
    public void run()  
    {  
        if(flag)  
        {  
            while(true)  
            {  
                synchronized(LockClass.locka)//a锁  
                {  
                    System.out.println(Thread.currentThread().getName()+"------if_locka");  
  
                    synchronized(LockClass.lockb)//b锁  
                    {  
                    System.out.println(Thread.currentThread().getName()+"------if_lockb");  
                    }  
                }  
            }  
        }  
        else  
        {  
            while(true)  
            {  
                synchronized(LockClass.lockb)//b锁  
                {  
                  System.out.println(Thread.currentThread().getName()+"------else_lockb");  
  
                    synchronized(LockClass.locka)//a锁  
                    {  
                   System.out.println(Thread.currentThread().getName()+"------else_locka");  
                    }  
                }  
            }  
        }  
    }  
}  
  
//定义两个锁  
class LockClass  
{  
    static Object locka = new Object();  
    static Object lockb = new Object();  
}  
  
class DeadLock  
{  
    public static void main(String[] args)  
    {  
        //创建2个进程,并启动  
        new Thread(new LockTest(true)).start();  
        new Thread(new LockTest(false)).start();  
    }  
}  

七:线程之间的沟通:

概述:多线程的主要作用是多个线程处理多个不同的任务,这就必然存在多个线程的协调问题。在运用多线程时,除了可以使用synchronized关键字还可以利用Objiect类中的 notify()、notifyall();wait()方法。让多个同时处理的线程之间能够主动的沟通协调。

八:加入线程:

概述:咋线程操作中,join()方法能够使当前的线程停下来等待另一个线程,就是说让另一一个线程 强制运行,其他线程无法运行,必须等待该线程的运行结束后方能继续运行。

实例::线程加入:

[java] view plaincopy在CODE上查看代码片派生到我的代码片
class Demo implements Runnable{  
    public void run(){  
        for (int x=0;x<=10 ;x++ ){  
            System.out.println(Thread.currentThread().getName()+"...."+x);  
        }  
    }  
}  
class JoinDemo{  
    public static void main(String[] arsg) throws Exception{  
        Demo d = new Demo();  
        Thread t1 = new Thread(d);  
        Thread t2 = new Thread(d);  
        t1.start();  
        t1.join();//主线程执行到t1线程的join方法后,主线程停止,等到t1线程run方法执行结束,主线程才会运行。也就是t1线程加入了主线程 
        t2.start();  
          
        for (int x=0;x<=10 ;x++ ){  
            System.out.println("main...."+x);  
        }  
        System.out.println("over");  
    }  
}  

八、停止线程:

实例:

class StopThread implements Runnable  
{  
    private boolean flag =true;  
    public  void run()  
    {  
        while(flag)  
        {  
            System.out.println(Thread.currentThread().getName()+"....run");  
        }  
    }  
    public void changeFlag()  
    {  
        flag = false;  
    }  
}  
  
class  StopThreadDemo  
{  
    public static void main(String[] args)   
    {  
        StopThread st = new StopThread();  
        Thread t1 = new Thread(st);  
        Thread t2 = new Thread(st);   
        t1.start();  
        t2.start();   
  
        int num = 0;  
        while(true)  
        {  
            if(num++ == 60)  
            {  
                t1.interrupt();//清除冻结状态  
                t2.interrupt();  
                st.changeFlag();//改变循环标记  
                break;  
            }  
            System.out.println(Thread.currentThread().getName()+"......."+num);  
        }  
        System.out.println("over");  
    }  
}  





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值