JAVA多线程
线程的创建的方式:
一:继承Thread类
由于JAVA里一个子类只能继承一个父类,所以继承Thread后的线程类无法拥有更多的功能,是最简单的创建线程的方法,学习阶段尝试线程感觉很方便
public class ThreadDemo1 {
public static void main(String[] args) {
Thread t = new MyThread();
t.start();
for (int i = 0; i < 10; i++) {
System.out.println("11111111111");
}
}
}
class MyThread extends Thread {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println("============");
}
}
}
二:实现Runnable接口
定义Runnable接口的实现类,只是实现了接口,可以继续继承类和实现接口,扩展性强,Runnable的实现类创建的对象只是任务对象,需要交给Thread进行包装,Thread类才是真正的线程对象
public class ThreadDemo2 {
public static void main(String[] args) {
Runnable target = new MyRunnable();
Thread t = new Thread(target);
t.start();
for (int i = 0; i < 10; i++) {
System.out.println("主线程执行输出:" + i);
}
}
}
class MyRunnable implements Runnable {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println("子线程执行输出:" + i);
}
}
}
三:实现Callable接口,用FutureTask创建新线程
将Callable的实现类包装到FutureTask里,再将FutureTask类作为任务对象包装到Thread类,可以调用FutureTask类的get()方法得到线程执行的返回值
(泛型里面是子线程执行结束后的返回值)
public class ThreadDemo3 {
public static void main(String[] args) {
Callable<String> call = new MyCallable(100);
FutureTask<String>f1 = new FutureTask<>(call);
Thread t1 = new Thread(f1);
t1.start();
Callable<String> call2 = new MyCallable(200);
FutureTask<String>f2 = new FutureTask<>(call2);
Thread t2 = new Thread(f2);
t2.start();
try {
String rs = f1.get();
System.out.println("线程1"+rs);
} catch (Exception e) {
e.printStackTrace();
}
try {
String rs2 = f2.get();
System.out.println("线程2"+rs2);
} catch (Exception e) {
e.printStackTrace();
}
}
}
class MyCallable implements Callable<String>{
private int n;
public MyCallable(int n) {
this.n = n;
}
public MyCallable() {
}
@Override
public String call() throws Exception {
int sum = 0;
for (int i = 1; i <=n ; i++) {
sum+=i;
}
return "执行的结果是:"+sum;
}
}
利用线程池创建新线程
一:Runnable的实现类在线程池里用execute执行
public class ThreadPoolDemo1 {
public static void main(String[] args) {
ExecutorService pool = new ThreadPoolExecutor(3, 5, 6, TimeUnit.SECONDS,
new ArrayBlockingQueue<>(5), Executors.defaultThreadFactory(),
new ThreadPoolExecutor.AbortPolicy());
Runnable target = new MyRunnable();
pool.execute(target);
pool.execute(target);
pool.execute(target);
pool.execute(target);
pool.execute(target);
pool.execute(target);
pool.execute(target);
pool.execute(target);
}
}
二:Callable的实现类用submit执行
public class ThreadPoolDemo2 {
public static void main(String[] args) throws Exception {
ExecutorService pool = new ThreadPoolExecutor(3, 5, 6, TimeUnit.SECONDS,
new ArrayBlockingQueue<>(5), Executors.defaultThreadFactory(),
new ThreadPoolExecutor.AbortPolicy());
Future<String> f1 = pool.submit(new MyCallable(100));
Future<String> f2 = pool.submit(new MyCallable(200));
Future<String> f3 = pool.submit(new MyCallable(300));
Future<String> f4 = pool.submit(new MyCallable(400));
Future<String> f5 = pool.submit(new MyCallable(500));
System.out.println(f1.get());
System.out.println(f2.get());
System.out.println(f3.get());
System.out.println(f4.get());
System.out.println(f5.get());
}
}
三:使用Executors的工具方法直接得到一个线程池对象
public class ThreadPoolDemo3 {
public static void main(String[] args) {
ExecutorService pool = Executors.newFixedThreadPool(3);
pool.execute(new MyRunnable());
}
}
Executors的工具方法底层还是采用ThreadPoolExecutor方法创建线程池
线程安全
使用synchronized关键字给线程加锁,一般使用对应的对象作为锁
静态方法可以使用类名.class作为锁
线程通信
使用notify唤醒等待的线程
使用wait将当前线程休眠
public class Phone {
private boolean flag = false;
public void run() {
new Thread(new Runnable() {
@Override
public void run() {
while (true) {
synchronized (Phone.this) {
if (!flag) {
try {
System.out.println("有新电话呼入,可以接听");
flag = true;
Thread.sleep(1000);
Phone.this.notify();
Phone.this.wait();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
try {
while (true) {
synchronized (Phone.this) {
if (flag) {
System.out.println("电话已接通,这两人正在聊天");
Thread.sleep(1000);
flag = false;
Phone.this.notify();
Phone.this.wait();
} else {
Phone.this.notify();
Phone.this.wait();
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
}
public static void main(String[] args) {
Phone phone = new Phone();
phone.run();
}
}
|