- 多线程是编程过程里必不可少的内容,学习多线程,就先要了解进程和线程的概念。
- 进程:是指当前正在运行的程序,是一个程序在内存里的执行区域;
- 线程:是在进程里的一个执行控制单元,执行路径;
实现多线程的方式有两种,一种是继承Thread类,一种是实现runnable接口。
1.继承Thread类
a) 根据API中的描述:创建新执行线程,继承Thread类方法是将类声明为 Thread
的子类。该子类应重写 Thread
类的 run
方法。
如下所示:
public class ThreadDemo extends Thread {@Overridepublic void run() {for (int i=0;i<100;i++){System.out.println(getName()+":"+i);}} }
getName()
方法用于 返回该线程的名称
b) 接下来可以分配并启动该子类的实例
如下所示:
public static void main(String[] args) {ThreadDemo xc = new ThreadDemo();xc.setName("thread1");xc.start();ThreadDemo xc2= new ThreadDemo();xc2.setName("thread2");xc2.start();}
setName(String name)
方法可以改变线程名称,使之与参数name
相同start()
方法使该线程开始执行;Java 虚拟机调用该线程的run
方法
2.实现runnable接口
a) API中的描述是:创建线程的另一种方法是声明实现 Runnable
接口的类。该类然后实现 run
方法。然后可以分配该类的实例,在创建 Thread
时作为一个参数来传递并启动
如下所示:
public class RunableDemo implements Runnable {public void run() {for (int i = 0; i < 100; i++) {System.out.println(Thread.currentThread().getName()+":"+i);}} }
currentThread()
我们实现了Runnable接口,接口里是没有getName方法的,所以如果我们想要获得到当前线程的基本信息,就需要用到Thread类的这个方法。API中描述:返回对当前正在执行的线程对象的引用,这个对象中是有getName()方法的。
b) 调用线程时,是使用Thread类,继承的对象作为一个参数传入
如下所示:
public static void main(String[] args) {RunableDemo xc = new RunableDemo();Thread thread = new Thread(xc);thread.setName("thread1");thread.start();Thread thread2 = new Thread(xc);thread2.setName("thread2");thread2.start();}
-
RunableDemo 实现了Runnable接口,这个对象作为runnable类型的对象传入Thread类中
- 最后通过start()方法进行启动,运行线程中的run()方法
在多线程中会出现需要同步操作的时候,例如扣费、减库存等,如果操作不用同步有可能导致库存为负数的情况。实现同步的方法如下:
1.同步代码块
关键字为synchronized,需要定义一把锁,这把锁需要所有的线程都共用,且锁可以为任意对象
代码如下:
//定义一把锁,在方法外以共用 Object obj = new Object();public void tongbu(){ synchronized(obj){ System.out.println("同步代码块");} }
2.同步方法
关键字也为synchronized
代码如下:
public synchronized void tongbu(){ System.out.println("同步方法"); }
注:同步方法的synchronized 也是有锁的,非静态方法调用的是类本身(this);静态方法因为加载在实体类之前,调用不到类本身,所以用到的是字节码对象(class类)