0 概述
线程是进程中一个独立控制单元,其控制着进程执行。一个进程中至少包含一个线程。
对于java程序来说都是jvm上运行的,运行java程序时候jvm就会启动一个进程,该进程中至少有一线程负责java程序执行,该线程运行的代码存在于main方法中,因此也称当前线程为主线程。下图给出了线程的几种状态。
1 线程创建
1.1第一种方式继承Thread类,要覆写其run方法。
覆写run方法的原因:
Thread类用于描述线程,该类定义就定义了一个功能,用于存储要运行的代码,也就是Thread类run方法,用于存储线程运行的代码。覆写run方法目的就是自定义代码存储在run方法中,让线程运行。
public class ThreadDemo extends Thread {
/**
* 覆写run方法
*/
@Override
public void run() {
System.out.println("ThreadDemo is run");
}
public static void main(String[] args) {
new ThreadDemo().start();
}
}
start方法创建一个新的线程并执行该线程的run方法。
{
/**
* This method is not invoked for the main method thread or "system"
* group threads created/set up by the VM. Any new functionality added
* to this method in the future may have to also be added to the VM.
*
* A zero status value corresponds to state "NEW".
*/
if (threadStatus != 0)
throw new IllegalThreadStateException();
/* Notify the group that this thread is about to be started
* so that it can be added to the group's list of threads
* and the group's unstarted count can be decremented. */
group.add(this);
boolean started = false;
try {
start0();
started = true;
} finally {
try {
if (!started) {
group.threadStartFailed(this);
}
} catch (Throwable ignore) {
/* do nothing. If start0 threw a Throwable then
it will be passed up the call stack */
}
}
}
主要是调用了private native void start0() 创建线程然后由虚拟机来执行run方法。
1.2 实现Runnable接口
public class public void run() {
if (target != null) {
target.run();
}
} {
public static void main(String[] args) {
/**
* 创建线程对象时候要明确要运行的代码
*/
Thread thread = new Thread(new RunnableDemo());
thread.start();
}
}
class RunnableDemo implements Runnable {
public void run() {
System.out.println("RunnableDemo run method");
}
}
Thread类中run方法,其中target是创建Thread类时候Runnable接口实现类
public void run() {
if (target != null) {
target.run();
}
}
2 多线程安全问题
2.1同步代码块
synchronized (对象)
{
//需要同步的代码块
}
同步方法锁是this对象
如果该方法被static修饰,同步锁是该类字节码文件对象即:类名.class
同步前提:
1.必须要有两个或者两个以上的线程(单线程不需要同步)
2.必须多个线程使用同一个锁
3.哪些语句在操作共享数据就需要同步。
好处:解决了线程安全问题
弊端:多个线程需要判断锁,较为消耗资源
线程不安全实例
public class ThreadDemo {
public static void main(String[] args) {
RunnableDemo runnableDemo = new RunnableDemo();
Thread thread1 = new Thread(runnableDemo);
Thread thread2 = new Thread(runnableDemo);
thread1.start();
thread2.start();
}
}
class RunnableDemo implements Runnable {
/**
* 多线程共享数据
*/
private int index = 2000;
public void run() {
while (true) {
if (index <= 0) {
break;
}
System.out.println(Thread.currentThread().getName() + "index:" + index--);
}
}
}
使用同步代码块的
public class ThreadDemo {
public static void main(String[] args) {
RunnableDemo runnableDemo = new RunnableDemo();
Thread thread1 = new Thread(runnableDemo);
Thread thread2 = new Thread(runnableDemo);
thread1.start();
thread2.start();
}
}
class RunnableDemo implements Runnable {
/**
* 多线程共享数据
*/
private int index = 2000;
public void run() {
while (true) {
if (index <= 0) {
break;
}
synchronized (this) {
System.out.println(Thread.currentThread().getName()+"index:" + index--);
}
}
}
}
Java.util.concurrent.locks包定义了两个锁类,ReentrantLock和ReentrantReadWriteLock类。下面给出使用ReentrantLock实例。
public class ThreadDemo {
public static void main(String[] args) {
RunnableDemo runnableDemo = new RunnableDemo();
Thread thread1 = new Thread(runnableDemo);
Thread thread2 = new Thread(runnableDemo);
thread1.start();
thread2.start();
}
}
class RunnableDemo implements Runnable {
/**
* 多线程共享数据
*/
private int index = 2000;
private ReentrantLock lock = new ReentrantLock();
public void run() {
while (true) {
if (index <= 0) {
break;
}
try {
lock.lock();
System.out.println(Thread.currentThread().getName() + "index:" + index--);
} catch (Exception ex) {
System.out.println(ex.getCause());
} finally {
lock.unlock();
}
}
}
}