疯狂java


您现在的位置: 疯狂软件 >> 新闻资讯 >> 正文

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 }

  复制代码

  复制代码

  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 }

  复制代码

  复制代码

  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 }

  复制代码

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

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

  区别:

  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 }

  复制代码