Java等待唤醒机制
package prc02;
public class StudentDemo {
public static void main(String[] args) {
Student s = new Student();
SetThread st = new SetThread(s);
GetThread gt = new GetThread(s);
Thread t1 = new Thread(st, "a");
Thread t2 = new Thread(gt, "b");
t1.start();
t2.start();
}
}
//学生类
public class Student {
String name;
int age ;
//声明一个变量
boolean flag ; //默认没有数据,如果true,则说明有数据
}
//消费者
public class GetThread implements Runnable {
private Student s;
public GetThread(Student s) {
this.s = s;
}
public void run() {
while (true) {
synchronized (s) {
if (!s.flag) {
try {
s.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(s.name + "---" + s.age);
// 修改标记
s.flag = false;// 消费者线程
// 通知对方(t1线程),消费者线程没有数据类,赶紧来消费
s.notify();// 唤醒t1线程....
}
}
}
}
//生产者
package prc02;
public class SetThread implements Runnable {
private Student s;
// 用构造函数使得他们用的都是同一个对象资源
public SetThread(Student s) {
this.s = s;
}
private int x = 0;
public void run() {
while (true) {
synchronized (s) {
if (s.flag) {
try {
s.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
if (x % 2 == 0) {
// 设置学生数据
s.name = "杨枝";
s.age = 24;
} else {
s.name = "小明";
s.age = 12;
}
x++;
// 修改标记
s.flag = true;// 有数据了
// 通知t2:消费者线程来消费数据
s.notify();// 唤醒等待这种状态...
}
}
}
}
线程组
public ThreadGroup(String name)构造一个新线程组
public Thread(ThreadGroup group,Runnable target ,String name)
package prac03;
public class Prac03 {
public static void main(String[] args) {
//method1();
method2();
}
private static void method2() {
ThreadGroup tg = new ThreadGroup("这是一个新的线程组") ;
//public Thread(ThreadGroup group,Runnable target ,String name){}
MyRunnable my = new MyRunnable() ;
Thread t1 = new Thread(tg, my, "线程1") ;
Thread t2 = new Thread(tg, my, "线程2") ;
ThreadGroup tg1 = t1.getThreadGroup() ;
ThreadGroup tg2 = t2.getThreadGroup() ;
System.out.println(tg1.getName());
System.out.println(tg2.getName());
System.out.println(Thread.currentThread().getThreadGroup().getName());
tg.setDaemon(true) ;
}
private static void method1() {
MyRunnable my = new MyRunnable() ;
Thread t1 = new Thread(my) ;
Thread t2 = new Thread(my) ;
//public final ThreadGroup getThreadGroup()返回该线程所属的线程组
ThreadGroup tg1 = t1.getThreadGroup() ;
ThreadGroup tg2 = t2.getThreadGroup() ;
String name1 = tg1.getName() ;
String name2 = tg2.getName() ;
子线程默认的线程组名称:main线程
System.out.println(name1);
System.out.println(name2);
System.out.println(Thread.currentThread().getThreadGroup().getName());
t1.start() ;
t2.start() ;
}
}
public class MyRunnable implements Runnable {
@Override
public void run() {
for(int x = 0 ; x <100 ; x ++){
System.out.println(Thread.currentThread().getName()+":"+x);
}
}
}
最终版生产者-消费者模式
将学生类成员变量私有化
提供两个同步方法
两个线程可以直接调用
public class StudentDemo {
public static void main(String[] args) {
Student s = new Student();
SetThread st = new SetThread(s);
GetThread gt = new GetThread(s);
Thread t1 = new Thread(st, "a");
Thread t2 = new Thread(gt, "b");
t1.start();
t2.start();
}
}
//学生类
public class Student {
private String name;
private int age;
private boolean flag; // 默认没有数据,如果true,则说明有数据
public synchronized void set(String name, int age) {
if (this.flag) {
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
this.name = name;
this.age = age;
// 修改标记
this.flag = true;// 有数据了
// 通知t2:消费者线程来消费数据
this.notify();// 唤醒等待这种状态...
}
public synchronized void get() {
if (!this.flag) {
try {
this.wait();// 调用的时候,会立即释放锁
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(this.name + "---" + this.age);
// 修改标记
this.flag = false;
this.notify();// 唤醒t1线程....
}
}
//消费者
public class GetThread implements Runnable {
private Student s;
public GetThread(Student s) {
this.s = s;
}
public void run() {
while (true) {
s.get();
}
}
}
//生产者
public class SetThread implements Runnable {
private Student s;
// 用构造函数使得他们用的都是同一个对象资源
public SetThread(Student s) {
this.s = s;
}
private int x = 0;
public void run() {
while (true) {
if (x % 2 == 0) {
s.set("小王", 32);
} else {
s.set("小明", 22);
}
x++;
}
}
}
线程池
很多子线程调用完毕不会立即被回收掉,而是会回到线程池中被多次利用(节约成本)
public class MyRunnable implements Runnable {
@Override
public void run() {
//for循环
for(int x = 0 ; x < 100 ; x ++){
System.out.println(Thread.currentThread().getName()+":"+x);
}
}
}
//测试类
public class ExecutorsDemo {
public static void main(String[] args) {
//创建线程池对象,使用Executors工厂类
//public static ExecutorService newFixedThreadPool(int nThreads)
ExecutorService pool = Executors.newFixedThreadPool(2) ;
//下来使用ExecutorService(跟踪多个异步任务)一些方法
//使用submit(Runnable target):提交多个任务
pool.submit(new MyRunnable()) ;
pool.submit(new MyRunnable()) ;
//结束线程池
pool.shutdown() ;
}
}
多线程的第三种实现方式
实现Callable接口
package prac04;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class Prac04 {
public static void main(String[] args) throws InterruptedException, ExecutionException {
ExecutorService pool = Executors.newFixedThreadPool(2) ;
//相当于start()
Future<Integer>f1=pool.submit(new MyCallable(100));
Integer i1= f1.get();
Future<Integer>f2=pool.submit(new MyCallable(10));
Integer i2= f2.get();
System.out.println(i1);
System.out.println(i2);
pool.shutdown();
}
}
package prac04;
import java.util.concurrent.Callable;
public class MyCallable implements Callable<Integer>{
private int number ;
public MyCallable(int number){
this.number = number ;
}
@Override
public Integer call() throws Exception {
int sum=0;
for(int x = 0 ; x < number ; x ++){
sum+=x;
}
return sum;
}
}
定时器 Timer:
public void schedule(TimerTask task,Date time)安排在指定的时间执行指定的任务
public void schedule(TimerTask task, long delay)在多少毫秒后执行指定任务
public void schedule(TimerTask task, long delay, long period)
在多少毫秒后,执行任务,并且每个多少毫秒重复执行
public void cancel()终止此计时器,丢弃所有当前已安排的任务