二、Java并行程序基础
2.1新建线程:
Thread thread = new Thread();
thread.start();
调用start()方法后自动调用run()方法,但线程新建时不能直接调用run()方法。
public class Client {
public static void main(String[] args) {
Thread thread = new Thread(){
@Override
public void run(){
System.out.println("run()...");
}
};
thread.start();
}
}
2.2注意:不要随便使用stop()结束一个进程,stop()方法会直接终止进程,并释放这个进程所持有的锁,容易导致不同的线程读错数据。
结束进程的方法:
public class Client extends Thread{
volatile boolean stopme = false;
public void Stopme(){
stopme = true;
}
@Override
public void run(){
while (true){
if (stopme){
System.out.println("exit by stopme");
break;
}
}
}
}
2.3中断进程
public void Thread.interrupt(); //中断进程,设置中断标志,但不会强制中断
public boolean Thread.isInterrupted(); //检查中断标志判断是否中断
public static boolean Thread.interrupt(); //判断是否被中断,并清除当前中断状态
2.4wait()和notify()
public class Client {
final static Object object = new Object();
// 等待
public static class Thread1 extends Thread{
@Override
public void run(){
synchronized (object){
System.out.println(System.currentTimeMillis()+":T1 start!");
try {
System.out.println(System.currentTimeMillis()+":T1 wait for Object!");
object.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(System.currentTimeMillis()+":T1 end!");
}
}
}
// 唤醒等待线程
public static class Thread2 extends Thread{
@Override
public void run(){
synchronized (object){
System.out.println(System.currentTimeMillis()+":T2 start! notify one thread");
object.notify();
System.out.println(System.currentTimeMillis()+":T2 end!");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
}
}
}
}
public static void main(String[] args) {
Thread1 thread1 = new Thread1();
Thread2 thread2 = new Thread2();
thread1.start();
thread2.start();
}
}
2.5挂起(suspend)和继续执行(resume)
不推荐使用这两个方法。
2.6等待线程结束(join)和谦让(yield)
public class Client {
public volatile static int i = 0;
public static class AddThread extends Thread {
@Override
public void run() {
for (i = 0; i < 10000000; i++);
}
}
public static void main(String[] args) throws InterruptedException {
AddThread addThread = new AddThread();
addThread.start();
addThread.join();
System.out.println(i);
}
}
注释join()方法后,i返回为0。
yield()会使当前线程让出cpu,重新参与cpu资源的争夺。
2.7volatile关键字
用volatile申明一个变量后,这个变量被修改后会通知其他的线程。
2.8synchronized关键字
实现线程间的同步,对同步的代码加锁,使得每一次只能有一个线程进入同步块,从而保证线程间的安全性。
2.9并发下的ArrayList
public class Client {
static ArrayList<Integer> arrayList = new ArrayList<Integer>(10);
public static class AddThread implements Runnable{
@Override
public void run(){
for (int i = 0; i < 1000000; i++) {
arrayList.add(i);
}
}
}
public static void main(String[] args) throws InterruptedException{
Thread thread1 = new Thread(new AddThread());
Thread thread2 = new Thread(new AddThread());
thread1.start();
thread2.start();
thread1.join();
thread2.join();
System.out.println(arrayList.size());
}
}
给程序运行会有三种结果
1)程序越界:
2)多线程冲突,导致结果变动
3)极少数情况会出现正确结果
改进方法:用Vector代替ArrayList
static Vector<Integer> arrayList = new Vector<Integer>(10);
2.10并发下的hashmap
同ArrayList问题,所以建议并发下用ConcurrentHashMap代替HashMap