方法一:
创建个类extends Thread这个类,重写run()方法,在run()方法里就是新的一条执行路径,触发方式是在main方法中new对象, 调用start()方法。
public class MyThread extends Thread{
@Override
public void run() {
//线程的任务
/*for (int i=0;i<10;i++){
System.out.println("子线程"+i);
}*/
}
}
方法二(常用):
创建个类implements Runnable这个接口,实现run()方法,在run()方法里就是新的一条执行路径,触发方式是在main方法中先new个对象,再new个Thread对象,将前面的对象传进去。
public class MyRunnable implements Runnable{
@Override
public void run() {
//线程的任务
/*for (int i=0;i<10;i++)
System.out.println("五六七八九"+i);*/
}
}
public class Demo {
public static void main(String[] args) {
//这是继承Thread的调用方法
/* MyThread myThread = new MyThread();
myThread.start();*/
//这是实现Runnable的调用方法
MyRunnable runnable = new MyRunnable();
Thread thread = new Thread(runnable);
thread.start();
for (int i=0;i<10;i++){
System.out.println("主线程"+i);
}
}
}
实现Runnable 与 继承Thread 相比的优势:
* 1.通过创建任务,然后给线程分配的方式实现多线程,更适合多个线程同时执行相同任务的情况。
* 2.可以避免单继承所带来的局限性。
* 3.任务与线程本身是分离的,提高了程序的健壮性。
* 4.后续学习的线程池技术,只接受Runnable类型的任务,而不接收Thread类型的线程。
方法三(不常用,作为了解)
Callbale
也是个接口,使用时重写call()方法。
注意现在写多线程,经常使用匿名内部类的方式,不用再新创建一个类了。还是使用第一种继承了Thread的方式:
格式:new Thread(){...这里重写run()方法}.start();
Thread类
常用方法:
strat():线程开始执行
setName(String name):将此线程的名称更改为参数name
setPriority(int newpriority):更改此线程的优先级
getName(String name):返回此线程的名称
getPriority(int newpriority):返回此线程的优先级
sleep(long millis):让线程休眠指定的毫秒数
currentThread():获取当前正在执行的线程对象
interrupt():给线程添加中断标记,产生异常到catch块,如果需要死亡则return
setDaemon(true):设置为守护线程,当最后一个用户线程结束时,守护线程自动死亡
线程不安全解决方案:
1:同步代码块(隐式锁)
格式:synchronized(锁对象){线程任务代码}
2.同步方法(隐式锁)
格式,在方法返回值前加上synchronized修饰
3.显式锁:Lock
先new对象 Lock lock = new ReentrantLock();-----这里有个构造方法,可以传参数fair:true代表是公平锁:Lock lock = new ReentrantLock(true);
将需要上锁的代码前调用方法lock.lock();
代码后lock.unlock();