实现线程的方式:
- 实现Runnable接口
- 继承Thread对象
- 使用ExecutorService、Callable、Future实现有返回结果的多线程
public class MyThread {
public static void main(String[] args) throws Exception {
// 实现Runnable接口创建线程
Thread t1 = new Thread(new Runnable() {
public void run() {
// to do
}
});
t1.start();
// 继承Thread创建线程
Thread t2 = new Thread() {
public void run() {
// to do
}
};
t2.start();
// 实现callable接口,使用线程池启动线程
ExecutorService pool = Executors.newFixedThreadPool(2);
// 创建多个有返回值的任务
List<Future<Integer>> list = new ArrayList<Future<Integer>>();
for (int i = 0; i < 2; i++) {
Callable<Integer> c = new Callable<Integer>() {
public Integer call() throws Exception {
// to do
return 0;
}
};
// 执行任务并获取Future对象
Future<Integer> f = pool.submit(c);
list.add(f);
}
// 关闭线程池
pool.shutdown();
// 获取所有并发任务的运行结果
for (Future f : list) {
// 从Future对象上获取任务的返回值,并输出到控制台
System.out.println(f.get().toString());
}
}
}
线程同步方式:
- 在方法上添加synchronized关键字, 如果加在静态方法上默认的lock为当前类的class, 如果加在非静态方法上则默认的lock为this
- 在代码块上添加synchronized关键字
- 使用信号量标记java.util.concurrent.Semaphore, 创建一个信号量标记,则一次只有一个线程执行
- 使用volatile关键字修饰要同步的变量(只能确保可见性,不能确保原子性。当只有一个写的线程时才可以使用)
- 使用ThreadLocal创建局部变量
- 使用java.util.concurrent.atomic包中的类创建同步变量, 如AtomicInteger
- 使用java.util.concurrent.locks包来创建锁, 通过编程方式获取和释放锁
public class TestThread{
private Object lock = new Object();
private Semaphore semaphore = new Semaphore(1);
/**
* 在代码块上加锁
*/
public void test1() {
synchronized(lock) {
// to do
}
}
/**
* 在非静态方法上添加synchronized,以this作为锁
*/
synchronized public void test2() {
// to do
}
/**
* 在静态方法上添加synchronized,以 TestThread.class作为锁, 号称“静态锁”
*/
synchronized public static void test3{
// to do
}
/**
* 使用信号标记来控制执行的线程数量
*/
public void test4() {
semaphore.acquire();// 获取信号标记的线程才会继续执行
// to do
semaphore.release(); // 执行完后释放信号标记
}
}