多线程有几种实现方法,同步有几种实现方法
多线程有两种实现方法:继承 Thread 类或者实现 Runnable 接口。
一.继承 Thread 类
//1、作为Thread的子类,并重写run方法。把多线程的业务写在run方法中 //2、默认实现是super.run(); //3、创建线程对象 //4、开启线程:谁抢到资源谁就先执行
常用方法
String getName()
返回该线程的名称。
static Thread currentThread()
返回对当前正在执行的线程对象的引用。
void setName(String name)
改变线程名称,使之与参数 name 相同。
static void sleep(long millis)
在指定的毫秒数内让当前正在执行的线程休眠(暂停执行),此操作受到系统计时器和调度程序精度和准确性的影响。
void start()
使该线程开始执行;Java 虚拟机调用该线程的 run 方法。
Thread(String name)
分配新的 Thread 对象。
public class Test1 {public static void main(String[] args) {//3、创建线程对象ThreadDemo t1 = new ThreadDemo("钢铁侠");ThreadDemo t2 = new ThreadDemo("美队");//4、开启线程:谁抢到资源谁就先执行t1.start();t2.start();//t1.run();//当做常规方法调用,且 不会发生多线程现象}}//1、作为Thread的子类,并重写run方法。把多线程的业务写在run方法中class ThreadDemo extends Thread{public ThreadDemo() {}public ThreadDemo(String name) {super(name);}@Overridepublic void run() {//2、默认实现是super.run();for (int i = 0; i < 10; i++) {System.out.println(getName()+i);}}}
二.多线程创建2:实现Runnable接口
*//1,实现Runnable接口,重写run()
//2,构造创建对象,传入Runnable子类
//3.开启线程
常用方法
void run()
使用实现接口 Runnable 的对象创建一个线程时,启动该线程将导致在独立执行的线程中调用对象的 run 方法。
public class Test2 {public static void main(String[] args) {MyThread t = new MyThread ();//2,构造创建对象,传入Runnable子类Thread target = new Thread(t);Thread target2 = new Thread(t);//开启线程target.start();target2.start();}}//1,实现Runnable接口,重写run()class MyThread implements Runnable{@Overridepublic void run() {for (int i = 0; i < 10; i++) {System.out.println(Thread.currentThread().getName()+" "+i);}}}
三.多线程创建3:实现Callable接口
implements Callable Runnable 和 Callable 的区别是, (1)Callable 规定的方法是 call(),Runnable 规定的方法是 run()。 (2)Callable 的任务执行后可返回值,而 Runnable 的任务是不能返回值得 (3)call 方法可以抛出异常,run 方法不可以 (4)运行 Callable 任务可以拿到一个 Future 对象,表示异步计算的结果。
总结
.第一种方法是将类声明为 Thread 的子类。该子类应重写 Thread 类的 run 方法,然后 在 run 方法里填写相应的逻辑代码。 第二种方法是实现 Runnable 接口,并编写 run 方法,相比继承 Thread 类创建线程的好处是 以实现接口的方式创建线程可以对类进行更好的扩展,该类可以继承其他类来扩展自身需 求,相比第一种方式更加灵活,扩展性强。 实现 Callable 接口创建线程与 Runnable 接口的不同之处在于:如果你想要在线程执行完 毕之后得到带有返回值的线程则实现 Callable 接口
实现同步也有两种方法:一种是同步方法,另一种是同步代码块。
同步方法是在方法返回类型前面加上 synchronized 关键字
同步代码块是 synchronized (这里写需要同步的对象){…}
同步锁
把有可能出现问题的代码包起来,一次只让一个线程执行。通过sychronized关键字实现同步。
当多个对象操作共享数据时,可以使用同步锁解决线程安全问题。
synchronizedsynchronized(对象){需要同步的代码;}
同步代码块是 synchronized (这里写需要同步的对象){…}
public class Test4 {public static void main(String[] args) {Ticket2 t = new Ticket2();Thread target = new Thread(t, "窗口1");Thread target2 = new Thread(t, "窗口2");Thread target3 = new Thread(t, "窗口3");Thread target4 = new Thread(t, "窗口4");target.start();target2.start();target3.start();target4.start();}}class Ticket2 implements Runnable {private int tic = 100;Object obj = new Object();@Overridepublic void run() {while (true) {// 把有线程安全问题的代码,用同步关键字包起来// 原理:用一个对象作为一把锁,给代码上锁,一个线程访问锁代码时,其他线程只能等待锁释放才能进来。// 多线程间要使用同一把锁才可以真的把代码锁住实现线程安全。 // synchronized (new Object()) {//锁了不同对象// synchronized (obj) {//锁了同一个对象//synchronized (Ticket2.class) {//锁了本类,针对于静态synchronized (this) {if (tic > 0) {try {Thread.sleep(100);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(tic--);}}}}}
同步方法是在方法返回类型前面加上 synchronized 关键字
public synchronized void run(){... ...}