线程
进程就是运行中的程序,线程是进程执行的任务,分为单线程和多线程
1. 线程的实现方式:继承Thread类或实现Runnable接口
1.1 Thread类
A类继承Thread类,重写run(),在主线程里创建该类的对象后,调用start()启动线程;
public class ThreadTest extends Thread{
public ThreadTest() {
}
public ThreadTest(String name) {
super(name);
}
@Override
public void run() {
for (int i=0;i<10;i++) {
System.out.println(getName()+"-出现次数:"+i);
}
}
}
public static void main(String[] args) {
ThreadTest one = new ThreadTest("飞机");
ThreadTest two = new ThreadTest("火车");
one.start();
two.start();
}
1.2 Runnable接口
实现步骤:
- A类实现Runnable接口
- A类重写run()方法
- 在主线程创建A类对象
- 创建Thread类对象,将A类对象当作构造方法参数传入
- 启动线程
public class RunnableTest implements Runnable{
@Override
public void run() {
System.out.println("我是接口线程");
}
}
public static void main(String[] args) {
RunnableTest test = new RunnableTest();
Thread two=new Thread(test);
two.start();
}
注:Thread.currentThread():获取当前类线程
解析:创建了两个线程对象,one线程和two线程。两个线程启动后互相抢占CPU资源,执行run里的语句。因此,当run()里有多条语句时,执行上是不可测的,one的语句还没执行完,two的语句就开始执行了.
2. 线程安全
2.1 同步代码块
public class SellTicket implements Runnable{
private int tickets=100;
private Object obj=new Object();
@Override
public void run() {
while (true) {
synchronized (obj) {
if (tickets > 0) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "正在出售第" + tickets + "张票");
tickets--;
}
}
}
}
}
2.2 同步方法
public class SellTicket implements Runnable {
private int tickets = 100;
private Object obj = new Object();
@Override
public void run() {
while (true) {
synchronized (this) {
if (tickets > 0) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "正在出售第" + tickets + "张票");
tickets--;
}else
sell();
}
}
}
public synchronized void sell() {
if (tickets > 0) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "正在出售第" + tickets + "张票");
tickets--;
}
}
}
public class SellTicket implements Runnable {
private static int tickets = 100;
private Object obj = new Object();
@Override
public void run() {
while (true) {
synchronized (SellTicket.class) {
if (tickets > 0) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "正在出售第" + tickets + "张票");
tickets--;
}else
sell();
}
}
}
public static synchronized void sell() {
if (tickets > 0) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "正在出售第" + tickets + "张票");
tickets--;
}
}
}
2.3 同步类
多线程环境下,使用StringBuffer,但Vector和Hashtable类一般不用,常用:Collerctions类下的方法转换线程安全的ArrayList、HashMap
Collections.synchronizedList(new ArrayList<>());
Collections.synchronizedMap(new HashMap<>());
2.4 Lock锁
@Override
public class SellTicket implements Runnable {
private static int tickets = 100;
private Lock lock=new ReentrantLock();
public void run() {
while (true) {
lock.lock();
if (tickets > 0) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "正在出售第" + tickets + "张票");
tickets--;
lock.unlock();
}
}
}
}