Java基础笔记-多线程

线程:

方式一:继承Thread类并且复写run方法.

格式:

class MyThread extends Thread

{

  public void run()

  {

    线程中要运行的代码.

  }

}

其步骤为:

1.定义类继承Thread类.

2.复习run方法.---->目的是:用于存储线程中要运行的代码,将自定义的代码存储在run方法中,让线程运行.

3.调用线程的start方法

  注意:不是调用run方法.

 

线程的名字:一般线程有默认的名字,形式为:Thread-编号,编号是从0开始标记的.

也可以获取当前运行线程的名字,用方法:Thread.currentThread().getName()

Thread.currentThread() 是用于获取当前线程的对象.(静态的).

自定义设置线程的名字可以用setName()或者构造函数来设置.

 

有关线程的继承方式的代码实例和练习:

 1 /*

 2 线程:步骤:

 3 1.定义一个类继承Thread

 4 2.复写类中的润方法

 5 3.创建一个对象(创建一个对象也就创建了一个线程)

 6 4.调用线程的start()方法,调用start方法后,启动了线程,同时也调用了run()方法.

 7 */

 8 class MyThread extends Thread //第一步

 9 {

10     public void run() //第二步

11     {

12         for(int x = 0; x < 60; x++)

13             System.out.println("MyThread run!====="+x);

14     }    

15 }

16 

17 

18 class ThreadDemo

19 {

20     public static void main(String args[])

21     {

22         MyThread mt = new MyThread();//创建了一个线程. //第三步

23         mt.start(); // 开启线程并运行该线程的run方法.     //第四步

24         //mt.run(); // 仅仅是对象调用方法,虽然创建了线程,但并未运行线程.

25         

26         for(int x = 0; x < 60; x++)

27             System.out.println("Hello World!====="+x);

28     }

29 }
View Code
 1 /*

 2 

 3 */

 4 class FirstThread extends Thread

 5 {

 6     //private String name;

 7     FirstThread(String name)

 8         {

 9             //this.name = name;

10             super(name); 

11         }

12     public void run()

13     {

14         for(int i = 1; i <= 50; i++)

15         {

16             //System.out.println(this.name+"FirstThread run.====="+i);

17             System.out.println((Thread.currentThread()==this)+"......"+this.getName()+"FirstThread run.====="+i);

18         }

19     }

20 }

21 

22 class ThreadTest

23 {

24     public static void main(String args[])

25     {

26         FirstThread ft1 = new FirstThread("First===");

27         FirstThread ft2 = new FirstThread("Second===");

28         ft1.start();

29         ft2.start();

30         

31         for(int i = 1; i <= 50; i++)

32         {

33             System.out.println("mainThread run.====="+i);

34         }

35     }

36 }
View Code
 1 /*

 2 售票窗口例子:

 3 多个窗口能够同时卖票.

 4 */

 5 

 6 class Ticket extends Thread

 7 {

 8     private static int ticket = 100; //不用static时候.两个窗口都会同时卖同号的票,即100张票连个窗口都会卖一次(相当于卖了200次)

 9     Ticket(String name)

10     {

11         super(name);

12     }

13     public void run()

14     {

15         while(true)

16         {

17             if(ticket>0)

18             {

19                 System.out.println(Thread.currentThread().getName()+"===卖票===="+ticket--);

20             }

21         }

22     }

23 }

24 

25 

26 class TicketDemo

27 {

28     public static void main(String args[])

29     {

30         Ticket t1 = new Ticket("窗口1");

31         Ticket t2 = new Ticket("窗口2");

32         t1.start();

33         t2.start();

34         

35     }

36 }

 


线程的第二种方式:

实现Runnable接口:

格式为:

class MyRunnable implements Runnable

{

  public void run()

  {

     线程中要运行的有关代码.

  }

其步骤一般为:

1.定义一个类实现Runnable接口.

2.复写Runnable接口中的run方法.

3.通过Thread类来创建一个对象.

4.将Runnable的子类的对象作为实际参数传给Thread类中的构造函数.

5.调用Thread类中的start方法.开启线程,并调用Runnable接口的子类的run方法.(可以理解为run方法又start方法开启调用的)

例如:

class MyRunnable implements Runnable  //步骤1

{

  public void run()  //步骤2

  {

    S.o.p();

  }

}

class RunnableDemo

{

  p.s.v.main()

  {

    MyRunnable mr = new MyRunnable();

    Thread t1 = new Thread(mr);  //步骤3---4

    t1.start();    //步骤5

  }

}

 1 /*

 2 售票窗口例子:

 3 多个窗口能够同时卖票.

 4 不使用静态的ticket来完成每个窗口的卖票,且不会卖重复的票.

 5 通过实现Runnable接口来完成.

 6 

 7 创建线程的第二种方法:

 8 实现Runnable接口来完成.

 9 步骤:

10 1.定义一个类实现(implements)Runnable接口

11 2.复写Runnable接口中的run方法

12 3.通过Thread类来创建对象

13 4.将Runnable接口的子类对象作为实际参数传给Thread类中的构造函数.

14 5.调用Thread类中的start方法开启线程,并调用Runnable接口的子类的run方法.

15 */

16 

17 

18 class Ticket implements Runnable

19 {

20     private int ticket = 100;  //    private static int ticket = 100; 

21     /*

22     由于Ticket并未继承Thread,该类并没有getName()的方法,因此是不能调用的.

23     Ticket(String name)

24     {

25         super(name);

26     }

27     */

28     public void run()

29     {

30         while(true)

31         {

32             if(ticket>0)

33             {

34                 System.out.println(Thread.currentThread().getName()+"===卖票====="+ticket--);

35             }

36         }

37     }

38 }

39 

40 

41 class RunnableTicketDemo

42 {

43     public static void main(String args[])

44     {

45         Ticket t = new Ticket();  //t是共享数据.

46         

47         /*

48         下面的方法不静态ticket时候会出现卖了200张票的情况,如何不静态 ticket =100,也自定义线程名且不出现卖200张票的情况????

49         */

50         //Ticket tt = new Ticket();

51         //Ticket ttt = new Ticket();

52         //Ticket tttt = new Ticket();

53         

54         //Thread t1 = new Thread(t,"窗口1");

55         //Thread t2 = new Thread(tt,"窗口2");

56         //Thread t3 = new Thread(ttt,"窗口3");

57         //Thread t4 = new Thread(tttt,"窗口4");

58         /*

59         下面的代码执行后,Thread.currentThread().getName()获取的是默认的线程名.

60         */

61         Thread t1 = new Thread(t);

62         Thread t2 = new Thread(t);

63         Thread t3 = new Thread(t);

64         Thread t4 = new Thread(t);

65         

66         t1.start();

67         t2.start();

68         t3.start();

69         t4.start();

70     }

71 }
View Code

继承方式和实现方式的多态的区别和特点:

实现方式:避免了单继承的局限性.一般定义线程时,建议使用实现方式.

区别:

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

2.实现Runnabel:线程的代码存放在Runnable接口的子类的run方法中.

 

最后是同步代码块,解决了多线程的安全性问题

格式为:

synchronized(对象)

{

需要被同步的代码块.

}

有关实现Runnable接口和同步的示例和练习代码:

 1 /*

 2 多线程的安全问题;

 3    打印出了票数为0.-1.-2等问题.

 4  

 5 问题分析,多条语句同时使用同一线程的共享数据时,一个线程只执行了一部分,还未执行完,另一个线程就参与进来执行了,导致共享数据的错误.

 6                     在if判断中,当ticket=1时,一个线程进去执行语句后,另一个线程也执行进来.

 7                     此时的ticket已经通过ticket--变成了0,从而导致了输出票数为0或者负数的情况.

 8 解决方案:

 9                     对操作多条共享数据的语句,让一个线程完全执行完毕后才让另一个线程执行,从而避免这种问题的发生.

10                     

11                     同步代码块.关键字:synchronized

12                     格式:

13                     synchronized(对象)

14                     {

15                         需要被同步的代码.

16                     {

17                     

18                     同步的条件:

19                     1.必须是多线程,单线程不能用同步.

20                     2.必须是多个线程使用同一个锁.

21                     必须保证同步中只有一个线程在运行.

22                     

23 同步的好处:解决了多线程的安全性问题.

24 缺点:每个线程都要判断锁,影响程序运行速度,耗费资源.

25 */

26 class Ticket implements Runnable

27 {

28     private int ticket = 100; 

29     Object obj = new Object();

30     public void run()

31     {

32         while(true)

33         {

34             synchronized(obj) //obj相当于锁.

35             {

36                 if(ticket>0)

37                 {

38                     // try{Thread.sleep(10);}catch(Exception e){}

39                     System.out.println(Thread.currentThread().getName()+"===卖票====="+ticket--);

40                 }

41             }

42         }

43     }

44 }

45 

46 class RunnableTicketSafeDemo

47 {

48     public static void main(String args[])

49     {

50         Ticket t = new Ticket();  //t是共享数据.

51         

52         Thread t1 = new Thread(t);

53         Thread t2 = new Thread(t);

54         Thread t3 = new Thread(t);

55         Thread t4 = new Thread(t);

56         

57         t1.start();

58         t2.start();

59         t3.start();

60         t4.start();

61     }

62 }

 

你可能感兴趣的:(java基础)