线程基本使用
1.继承Thread,覆盖run()方法
public class ThreadDemo1 extends Thread{ @Override public void run() { for (int i = 0; i < 20; i++) { /* System.out.println("run"+i); Thread thread = Thread.currentThread(); System.out.println(thread); String name = thread.getName(); System.out.println(name);*/ System.out.println(Thread.currentThread().getName()+"===>"+i); } } } public class MainTest { public static void main(String[] args) { ThreadDemo1 threadDemo1 = new ThreadDemo1(); ThreadDemo1 threadDemo11 = new ThreadDemo1(); threadDemo1.start(); threadDemo11.start(); for (int i = 0; i < 20; i++) { System.out.println("main"+i); } } }
2.实现Runnable接口,覆盖run()方法
public class RunnableImpl implements Runnable { @Override public void run() { System.out.println(Thread.currentThread().getName()+"传统"); } }
public class TestDemo { public static void main(String[] args) { // 传统方式 RunnableImpl runnable = new RunnableImpl(); Thread t1 = new Thread(runnable); t1.start(); // 匿名内部类 Runnable runnable1 = new Runnable() { @Override public void run() { System.out.println(Thread.currentThread().getName() + "匿名内部类"); } }; // 匿名内部类的简化 new Thread(runnable1).start(); new Thread(new Runnable() { @Override public void run() { System.out.println(Thread.currentThread().getName() + "匿名内部类简化"); } }).start(); //使用lambda表达式 new Thread(() ->{ System.out.println(Thread.currentThread().getName()+"lambda表达式"); } ).start(); } }
3.线程案例
public class RunnableImpl implements Runnable { private int ticket=100; @Override public void run() { while (true){ if (ticket>0){ try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+"正在卖第"+ticket+"张票"); ticket--; } } } } public class TicketDemo { public static void main(String[] args) { RunnableImpl runnable = new RunnableImpl(); Thread t1 = new Thread(runnable); Thread t2 = new Thread(runnable); Thread t3 = new Thread(runnable); t1.start(); t2.start(); t3.start(); } }
存在一票多售和无效票,需要解决线程安全问题
在可能出现线程问题的代码上添加同步锁,保证锁为同一把就完了;新创建一个对象,或者this当前类,或者同步代码块,同步方法;静态方法使用静态变量也有可能出现线程问题,还是得使用同步机制。
public class RunnableImpl implements Runnable { private int ticket=100; Object object=new Object(); @Override public void run() { while (true){ synchronized (object){ if (ticket>0){ try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+"正在卖第"+ticket+"张票"); ticket--; } } } } }
public class RunnableImpl implements Runnable { private int ticket=100; @Override public void run() { while (true){ payTicket(); } } public synchronized void payTicket(){ if (ticket>0){ try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+"正在卖第"+ticket+"张票"); ticket--; } } }
public class RunnableImpl implements Runnable { private int ticket=100; @Override public void run() { while (true){ synchronized (this){ if (ticket>0){ try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+"正在卖第"+ticket+"张票"); ticket--; } } } } }
public class RunnableImpl implements Runnable { private static int ticket=100; @Override public void run() { while (true){ payTicket(); } } public static synchronized void payTicket(){ if (ticket>0){ try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+"正在卖第"+ticket+"张票"); ticket--; } } }
public class RunnableImpl implements Runnable { private int ticket=100; Lock lock=new ReentrantLock(); @Override public void run() { while (true){ lock.lock(); if (ticket>0){ try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+"正在卖第"+ticket+"张票"); ticket--; } lock.unlock(); } } }
总结:这两种基本的创建线程的方式是使用场景而定,特别是使用线程池的时候,runnable作为参数传递。当然线程的状态,start()和run()的区别,其他的线程实现方式,并包......