JAVA多线程学习

一. java多线程的基本实现

1.实现的方式:

  • 继承thread类:
1
2
3
4
5
6
7
class ThreadA extends Thread{
...

public void run(){
//线程的业务逻辑
}
}
1
2
ThreadA threadA = new ThreadA();
threadA.start();
  • 实现runnable接口
1
2
3
4
5
6
7
class RunnableA implements Runnable{
...

public void run(){
//线程的业务逻辑
}
}
1
2
RunnableA runnableA = new RunnableA();
new Thread(runnableA).start();

2.thread类常用的方法:

  • 构造方法:thread(),thread(Runnable target)
  • 启动线程:void start()
  • 线程休眠:static void sleep()
  • 当前线程等待join的线程结束:void join()
  • 当前运行线程释放处理器资源:static void yield()
  • 获取当前的运行线程:static Thread currentThread()

3.wait()、notify()和notifyAll()

  • 在使用wait()、notify()和notifyAll()之前,先必须获得该对象的锁,而对应的状态变量也是由该对象锁保护的。
  • wait()是通知当前线程去等待,并且释放锁资源,等待其他线程调用notify()或者notifyAll()方法,恢复线程执行。
  • notify()唤醒一个等待的线程,notifyAll()唤醒所有等待的线程。被唤醒的线程必须等待锁被释放,才能去获取锁从而执行接下来的操作。

二. java多线程的高级方法

1.实现的方式:

  • Future接口+Callable接口
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
public class Test{
ExecutorService executor = Executors.newCachedThreadPool();
Task task = new Task();
Future<Integer> result = executor.submit(task);
executor.shutdown();

...

try {
System.out.println("task运行结果"+result.get());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}

class Task implements Callable<Integer>{
@Override
public Integer call() throws Exception {
System.out.println("子线程在进行计算");
Thread.sleep(3000);
int sum = 0;
for(int i=0;i<100;i++)
sum += i;
return sum;
}
}
  • FutureTask类+Callable接口
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
public class Test {
    public static void main(String[] args) {
        //第一种方式
        ExecutorService executor = Executors.newCachedThreadPool();
        Task task = new Task();
        FutureTask<Integer> futureTask = new FutureTask<Integer>(task);
        executor.submit(futureTask);
        executor.shutdown();
         
        //第二种方式,注意这种方式和第一种方式效果是类似的,只不过一个使用的是ExecutorService,一个使用的是Thread
        /*Task task = new Task();
        FutureTask<Integer> futureTask = new FutureTask<Integer>(task);
        Thread thread = new Thread(futureTask);
        thread.start();*/

         
...
         
        try {
            System.out.println("task运行结果"+futureTask.get());
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
         
        System.out.println("所有任务执行完毕");
    }
}
class Task implements Callable<Integer>{
    @Override
    public Integer call() throws Exception {
        System.out.println("子线程在进行计算");
        Thread.sleep(3000);
        int sum = 0;
        for(int i=0;i<100;i++)
            sum += i;
        return sum;
    }
}

callable接口一般是配合ExecutorService来使用的,ExecutorService可以通过Executors提供的工厂方法来生成。ExecutorService提供了submit方法,将一个callable任务提交,并且返回一个与callable任务绑定的future对象,来查询执行结果。常用的2个submit方法的实现如下:

1
2
<T> Future<T> submit(Callable<T> task);
Future<?> submit(Runnable task);

2.future接口提供的方法

  • 取消任务:boolean cancel(boolean mayInterruptIfRunning)
  • 查询任务是否被成功取消:boolean isCancelled();
  • 查询任务是否完成:boolean isDone();
  • 获取执行结果(会产生阻塞):
    • V get() throws InterruptedException, ExecutionException;
    • V get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException;

三. java的并发集合

  • hashtable: Hashtable 提供了一种易于使用的、线程安全的、关联的map功能,这当然也是方便的。然而,线程安全性是凭代价换来的―― Hashtable 的所有方法都是同步的。
  • hashmap:它通过提供一个不同步的基类和一个同步的包装器 Collections.synchronizedMap ,解决了线程安全性问题。 通过将基本的功能从线程安全性中分离开来。但hashtable和synchronizedMap只是提供了有条件地线程安全――所有单个的操作都是线程安全的,但是多个操作组成的操作序列却可能导致数据争用,因为在操作序列中控制流取决于前面操作的结果。
  • ConcurrentHashMap:多个读操作几乎总可以并发地执行,同时进行的读和写操作通常也能并发地执行,而同时进行的写操作仍然可以不时地并发进行
  • CopyOnWriteArrayList:在那些遍历操作大大地多于插入或移除操作的并发应用程序中,一般用 CopyOnWriteArrayList 类替代 ArrayList。CopyOnWriteArrayList 含有对一个不可变数组的一个可变的引用,因此,只要保留好那个引用,您就可以获得不可变的线程安全性的好处,而且不用锁 定列表。

其他

  • volatile
  • 多线程退出:设置flag标志位,用volatile修饰符。不能用stop()和interrupt()。

当前浏览器不支持博客完整功能。如果要获得最佳体验,请点击右上角···,复制链接,并在其它浏览器打开