public static void main(String[] args) {
Thread t = new BakDataThread();
t.setName("备份数据的线程");
//启动线程之前,将线程设置为守护线程
t.setDaemon(true);
t.start();
//主线程:主线程是用户线程
for(int i=0;i<10;i++){
System.out.println(Thread.currentThread().getName()+"--->"+i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class BakDataThread extends Thread{
public void run(){
int i=0;
while(true){
System.out.println(Thread.currentThread().getName()+"--->"+(++i));
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public class Day01 {
public static void main(String[] args) throws ParseException {
//创建定时器对象
Timer timer = new Timer();
//指定定时任务
//timer.schedule(定时任务,第一次执行时间,间隔多久执行一次);
SimpleDateFormat sdf =new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date firstTime =sdf.parse("2021-05-13 15:07:00");
timer.schedule(new LogTimerTask(),firstTime,1000*10);
}
}
//编写一个定时任务类
//假设这是一个记录日志的定时任务
class LogTimerTask extends TimerTask {
@Override
public void run() {
SimpleDateFormat sdf =new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String strTime =sdf.format(new Date());
System.out.println(strTime+":完成了一次数据备份!");
}
}
改写为匿名内部类
public class Day01 {
public static void main(String[] args) throws ParseException {
//创建定时器对象
Timer timer = new Timer();
//指定定时任务
//timer.schedule(定时任务,第一次执行时间,间隔多久执行一次);
SimpleDateFormat sdf =new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date firstTime =sdf.parse("2021-05-13 15:07:00");
// timer.schedule(new LogTimerTask(),firstTime,1000*10);
timer.schedule(new TimerTask(){
@Override
public void run() {
SimpleDateFormat sdf =new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String strTime =sdf.format(new Date());
System.out.println(strTime+":完成了一次数据备份!");
}
},firstTime,1000*10);
}
}
public class Day01 {
/*
实现线程的第三种方式
实现Collable接口
*/
public static void main(String[] args) throws Exception {
//第一步:创建一个“未来任务类”对象。
// 参数非常重要,需要给一个Collable接口实现对象
FutureTask task =new FutureTask(new Callable() {
@Override
public Object call() throws Exception {//call()方法就相当于run方法。只不过这个有返回值
//线程执行一个任务,执行之后可能会有一个执行结果
//线程模拟
System.out.println("call method begin");
Thread.sleep(1000*10);
System.out.println("call method end!");
int a=100;
int b=200;
return a+b;//自动装箱(300结果变成Interger)
}
});
//创建线程对象
Thread t = new Thread(task);
//启动线程
t.start();
//这里是main方法,这里在主线程中。
//在主线程中,怎么获取t线程的返回结果?
//get()方法的执行会导致“当前线程阻塞”导致
// 效率低但优点可以拿到线程的执行结果
Object obj =task.get();
System.out.println("线程执行结果"+obj);
//main方法这里的程序想要执行必须等待get()方法的结束
//而get()方法可能会需要很久,因为get()方法是为了拿到另一个线程的执行结果
//另一个线程执行是需要时间的。
System.out.println("fianlly my turn ");
}
}
wait()和notify()方法的理解
/*
模拟这样一个需求,
仓库采用List集合。
List集合中假设只能存储1个元素
1个元素就表示仓库满了
0个元素表示仓库空了
保证List集合中永远最多存储1个元素
效果:生产一个消费一个
*/
public class Day01 {
public static void main(String[] args) {
//创建一个仓库对象,共享的
List list =new ArrayList();
//创建两个线程对象
//生产者线程
Thread t1=new Thread(new Producer(list));
//消费者线程
Thread t2=new Thread(new Consumer(list));
t1.setName("生产者线程");
t2.setName("消费者线程");
t1.start();
t2.start();
}
}
//生产线程
class Producer implements Runnable{
//仓库;
private List list;
public Producer(List list){
this.list=list;
}
@Override
public void run() {
//一直生产(使用死循环来模拟一直生产)
while(true){
//给仓库对象加锁
synchronized (list){
if (list.size()>0){//说明几何元素已经有一个元素了
try {
//当前的线程进入等待状态,并且释放Producer之前占有的list集合的锁
list.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//程序能够执行到这里说明仓库是空的,可以生产
Object obj = new Object();
list.add(obj);
System.out.println(Thread.currentThread().getName()+"--->"+obj);
//唤醒消费者进行消费
list.notify();
}
}
}
}
//消费线程
class Consumer implements Runnable{
//仓库
private List list;
public Consumer(List list){
this.list=list;
}
@Override
public void run() {
//一直消费
while (true) {
//给仓库对象加锁
synchronized (list) {
if (list.size() == 0) {
try {
//仓库已经空了,消费者进入等待,释放掉consumer占用的list锁
list.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//程序能够运行到此处,说明仓库中有数据进行消费
Object obj=list.remove(0);
System.out.println(Thread.currentThread().getName()+"--->"+obj);
//唤醒生产者生产
list.notify();
}
}
}
}
线程池