多线程有几种实现方法,同步有几种实现方法
多线程有两种实现方法:继承 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);
}
@Override
public 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{
@Override
public 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关键字实现同步。
当多个对象操作共享数据时,可以使用同步锁解决线程安全问题。
synchronized
synchronized(对象){
需要同步的代码;
}
同步代码块是 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();
@Override
public 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()
{
... ...
}