Java分享笔记:创建多线程 & 线程同步机制
[1] 创建多线程的两种方式
1.1 通过继承Thread类创建多线程
1.定义Thread类的子类,重写run()方法,在run()方法体中编写子线程要执行的功能。
2.创建子线程的实例对象,相当于新建了一条子线程。
3.调用子线程的start()方法,子线程启动并执行run()方法中的功能。
1.2 通过实现Runnable接口创建多线程
1.定义一个类,实现Runnable接口,重写run()方法,在run()方法体中编写子线程要执行的功能。
2.创建实现类的对象。
3.调用Thread类的有参构造函数,将上述实现类对象作为形参传入,创建Thread类的对象。该对象相当于一条新线程。
4.调用Thread对象的start()方法,子线程启动并执行run()方法中的功能。
[2] 线程同步机制
当多条线程操作共享数据时,会出现线程安全问题。为了解决这一问题,需要保证不同线程在访问同一数据时保持一定的顺序,即“线程的同步机制”。实现该机制有两种方法:同步代码块,同步方法。前者可以指定任意对象作为监视器,后者只能默认使用当前对象作为监视器。故使用同步方法保证线程同步有一定的局限性。
[3] 代码实例
3.1 通过继承Thread类创建多线程,并使用同步代码块的方式保证线程的同步。
1 //通过继承Thread类的方式创建多线程 2 //多条线程操作同一个共享资源,存在线程安全问题 3 //通过同步代码块的方式使线程同步 4 package pack01; 5 6 //定义子线程 7 class SubThread extends Thread { 8 9 private static int i = 1; 10 static Object lock = new Object(); //创建静态对象作为监视器 11 12 // 子线程要实现的功能:将静态变量i累加到100,并打印每次的累加结果 13 // 由于多条线程会同时操作静态变量i,故需要保证线程的同步 14 public void run() { 15 16 while (true) { 17 18 synchronized (lock) { 19 if (i <= 100) { 20 System.out.println(Thread.currentThread().getName() + "----" + i); 21 ++i; 22 23 } else { 24 break; 25 } 26 } 27 } 28 29 } 30 } 31 32 public class MulThread { 33 public static void main(String[] args) { 34 35 SubThread st1 = new SubThread(); 36 SubThread st2 = new SubThread(); 37 38 // 设置线程名称 39 st1.setName("ONE####"); 40 st2.setName("TWO...."); 41 42 // 启动线程 43 st1.start(); 44 st2.start(); 45 } 46 }
3.2 通过实现Runnable接口创建多线程,使用同步方法保证线程同步。
1 //通过实现Runnable接口的方式创建多线程 2 //多条线程操作同一个共享资源,存在线程安全问题 3 //通过使用同步方法保证线程的同步 4 package pack01; 5 6 class Sub implements Runnable{ 7 8 private static int i=1; //被多条线程共同操作的静态变量 9 10 public void run() { 11 while(true) { 12 printI(); 13 } 14 } 15 16 public synchronized void printI() { //将要需要同步的代码封装进一个同步方法中 17 18 if(i<=100) { 19 System.out.println( Thread.currentThread().getName() + "----" + i ); 20 ++i; 21 } else { 22 System.exit(0); 23 } 24 } 25 } 26 27 public class MulThread2 { 28 public static void main(String[] args) { 29 30 Sub sub = new Sub(); 31 32 Thread t1 = new Thread(sub);//将Runnable接口的实现类对象作为参数,传给Thread构造器 33 Thread t2 = new Thread(sub); 34 35 t1.setName("ONE####"); 36 t2.setName("TWO...."); 37 38 t1.start(); 39 t2.start(); 40 } 41 }
注:希望与各位读者相互交流,共同学习进步。