多线程(二)
七、获取线程名字和设置名字
* 1.获取名字
* 通过getName()方法获取线程对象的名字
* 2.通过构造函数可以传入String类型的名字
Java Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | new Thread("xxx") { public void run() { for(int i = 0; i < 1000; i++) { System.out.println(this.getName() + "....aaaaaaaaaaaaaaaaaaaaaaa"); } } }.start(); new Thread("yyy") { public void run() { for(int i = 0; i < 1000; i++) { System.out.println(this.getName() + "....bb"); } } }.start(); |
* 3.通过setName(String)方法可以设置线程对象的名字
Java Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | Thread t1 = new Thread() { public void run() { for(int i = 0; i < 1000; i++) { System.out.println(this.getName() + "....aaaaaaaaaaaaaaaaaaaaaaa"); } } }; Thread t2 = new Thread() { public void run() { for(int i = 0; i < 1000; i++) { System.out.println(this.getName() + "....bb"); } } }; t1.setName("线程1"); t2.setName("线程2"); t1.start(); t2.start(); |
八、获取当前线程对象
Java Code
1 2 3 4 5 6 7 8 9 | new Thread(new Runnable() { public void run() { for(int i = 0; i < 1000; i++) { System.out.println(Thread.currentThread().getName() + "...bb"); } } }).start(); Thread.currentThread().setName("我是主线程"); //获取主函数线程的引用,并改名字 System.out.println(Thread.currentThread().getName()); //获取主函数线程的引用,并获取名字 |
九、休眠线程、守护线程、加入线程
1,Thread.sleep(毫秒,纳秒), 控制当前线程休眠若干毫秒1秒= 1000毫秒 1秒 = 1000 * 1000 * 1000纳秒 1000000000
Java Code
1 2 3 4 5 6 7 8 9 10 11 12 | new Thread() { public void run() { for(int i = 0; i < 10; i++) { System.out.println(getName() + "...bb"); try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } } } }.start(); |
Java Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | Thread t1 = new Thread() { public void run() { for(int i = 0; i < 50; i++) { System.out.println(getName() + "...aaaaaaaaaaaaaaaaaaaaaa"); try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } } } }; Thread t2 = new Thread() { public void run() { for(int i = 0; i < 5; i++) { System.out.println(getName() + "...bb"); try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } } } }; t1.setDaemon(true); //将t1设置为守护线程 t1.start(); t2.start(); |
3, join(), 当前线程暂停, 等待指定的线程执行结束后, 当前线程再继续,join(int), 可以等待指定的毫秒之后继续
Java Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | Thread t2 = new Thread() { public void run() { for(int i = 0; i < 50; i++) { if(i == 2) { try { //t1.join(); //插队,加入 t1.join(30); //加入,有固定的时间,过了固定时间,继续交替执行 Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println(getName() + "...bb"); } } }; t1.start(); t2.start(); |
十、同步代码块与同步方法
* 1.什么情况下需要同步
* 当多线程并发, 有多段代码同时执行时, 我们希望某一段代码执行的过程中CPU不要切换到其他线程工作. 这时就需要同步.
* 如果两段代码是同步的, 那么同一时间只能执行一段, 在一段代码没执行结束之前, 不会执行另外一段代码.
* 2.同步代码块
* 使用synchronized关键字加上一个锁对象来定义一段代码, 这就叫同步代码块
* 多个同步代码块如果使用相同的锁对象, 那么他们就是同步的
Java Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | class Printer { Demo d = new Demo(); public static void print1() { synchronized(d){ //锁对象可以是任意对象,但是被锁的代码需要保证是同一把锁,不能用匿名对象 System.out.print("北"); System.out.print("京"); System.out.print("烤"); System.out.print("鸭"); System.out.print("\r\n"); } } public static void print2() { synchronized(d){ System.out.print("宫"); System.out.print("保"); System.out.print("鸡"); System.out.print("丁"); System.out.print("\r\n"); } } } |
* 3.使用synchronized关键字修饰一个方法, 该方法中所有的代码都是同步的
Java Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | class Printer { public static void print1() { synchronized(Printer.class){ //锁对象可以是任意对象,但是被锁的代码需要保证是同一把锁,不能用匿名对象 System.out.print("北"); System.out.print("京"); System.out.print("烤"); System.out.print("鸭"); System.out.print("\r\n"); } } /* * 非静态同步函数的锁是:this * 静态的同步函数的锁是:字节码对象 */ public static synchronized void print2() { System.out.print("宫"); System.out.print("保"); System.out.print("鸡"); System.out.print("丁"); System.out.print("\r\n"); } } |
十一、多线程安全问题
* 多线程并发操作同一数据时, 就有可能出现线程安全问题
* 使用同步技术可以解决这种问题, 把操作数据的代码进行同步, 不要多个线程一起操作
Java Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 | public class Demo2_Synchronized { /** * @param args * 需求:铁路售票,一共100张,通过四个窗口卖完. */ public static void main(String[] args) { TicketsSeller t1 = new TicketsSeller(); TicketsSeller t2 = new TicketsSeller(); TicketsSeller t3 = new TicketsSeller(); TicketsSeller t4 = new TicketsSeller(); t1.setName("窗口1"); t2.setName("窗口2"); t3.setName("窗口3"); t4.setName("窗口4"); t1.start(); t2.start(); t3.start(); t4.start(); } } class TicketsSeller extends Thread { private static int tickets = 100; static Object obj = new Object(); public TicketsSeller() { super(); } public TicketsSeller(String name) { super(name); } public void run() { while(true) { synchronized(obj) { if(tickets <= 0) break; try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(getName() + "...这是第" + tickets-- + "号票"); } } } } |