java timer线程结束_java-多线程操作全(Thread)-Timer简单使用

一、 多线程概念和作用

线程指进程中的一个执行场景,也就是执行流程,那么进程和线程的区别是什么

1.每个进程是一个应用程序,都有独立的内存空间

2.同一个进程中的线程共享其进程中的内存和资源

(共享的内存是堆内存和方法内存,栈内存不共享,每个线程有自己的堆内存)

进程:进程对应一个应用程序

现在的计算机都是支持多进程的,在同一个操作系统中,可以同时启动多个进程

多进程的作用:

* 单进程只能做一件事 : 一边玩游戏,一边听音乐不是同时运行,而是进程之间的频繁调度,切换速度极高,感觉是同时进行。

* 多线程的作用不是提高执行速度,而是提高CPU的使用率。进程和进程之间的内存是独立的、

* 线程:是进程中的执行场景。一个进程可以启动多个线程。

* 多线程的作用:不是为了提高执行速度,而是为了提高应用程序的使用率

* java程序的运行原理

* java命令启动java虚拟机,启动JVM,等于启动一个应用程序,表明启动一个进程。该进程会自动启动一个“主线程”,然后主线程去调用某各类的main方法。

* 所以,main方法运行在主线程中。在此之前的所有程序都是单线程的。

二、线程的创建和启动

*Java虚拟机的主线程入口是main方法,用户可以自己创建线程,创建方式有两种

*1.继承Thread类

*2.实现Runnable接口(推荐使用Runnable)

*继承Thread类

*采用 Thread类创建线程,用户只需要继承 Thread,覆盖 Thread中的run方法,父类 Thread中的run方法没有抛出异常,那么子类也不角能抛出异常,最后采用start启动线程即可

实现Runnable接口

Thread对象本身就实现了 Runnable接口,但一般建议直接使用 Runnable接口来写多线程程序,因为接口会比类带来更多的好处

三、java语言中实现多线程第一种方式

1.继承java.lang.Thread

2.重写run方法

三个知识点 :定义线程 、创建线程、启动线程

packagecom.steven.demo;importjava.lang.Thread;public classThreadTest {public static voidmain(String[] args) {

Thread thread= newStudent();//启动线程

thread.start();//打印Run:0~9//start方法执行完瞬间结束,告诉JVM再分配一个新的线程 给t线程//是随机分配的,没有规律//run不需要手动调用,系统程序启动之后会自动调用方法//thread.run();//这是普通方法的调用,这样做程序只有一个线程,run方法结束之后,下边的程序才会执行

for (int i = 0; i < 5; i++) {

System.out.println("main"+i);

}//有了多线程之后,main方法结束只是主线程中没有方法栈帧了 但是其他线程或者其他栈中还有栈帧 main方法结束,程序可能还在运行

}

}class Student extendsThread {//重写Run方法

public voidrun() {for (int i = 0; i < 10; i++) {

System.out.println("Run:"+i);

}

}

}

四、java语言中实现多线程第二种方式

1.写一个类实现

2.重写run方法

packagecom.steven.demo;importjava.lang.Runnable;importjava.lang.Thread;public classThreadTest02 {public static voidmain(String[] args) {//创建线程:

Thread thread = new Thread(newTeacher());//启动线程

thread.start();

}

}class Teacher implementsRunnable {//重写Run方法

public voidrun() {for (int i = 0; i < 10; i++) {

System.out.println("Run:"+i);

}

}

}

五、掌握线程方法:

1.获取当前线程的对象 Thread.currentThread()

2.给线程起名t.setName()

3.获取线程的名字:t.getName()

packagecom.steven.demo;public classThreadTest03 {public static voidmain(String[] args) {//获取当前线程的对象 main主线程

Thread thread =Thread.currentThread();//获取当前线程的名字

System.out.println("当前名称的名称"+thread.getName());//当前名称的名称main

Thread t1= new Thread(newArrayTest());//给线程起名

t1.setName("Steven");

t1.start();//线程的名称Steven

Thread thread2= new Thread(newArrayTest());//给线程重命名

thread2.setName("珂珂");

thread2.start();//线程的名称珂珂

}

}class ArrayTest implementsRunnable {public voidrun() {

Thread thread= Thread.currentThread();//获取当前线程的对象

System.out.println("线程的名称"+thread.getName());

}

}

六、线程的优先级

优先级高的获取CPU时间片,相对多一些

最高:10

最小:1

默认:5

优先级1-10

优先级高的线程,会得到CPU的时间多一些,优先执行完成

public classThreadTest04 {public static voidmain(String[] args) {

System.out.println("最高"+Thread.MAX_PRIORITY);

System.out.println("最小"+Thread.MIN_PRIORITY);

System.out.println("默认"+Thread.NORM_PRIORITY);

Thread t1= new Thread(newKeKe());

t1.setName("t1");

Thread t2= new Thread(newKeKe());

t2.setName("t2");//获取线程的优先级

System.out.println("t1优先级"+t1.getPriority());

System.out.println("t2优先级"+t2.getPriority());//设置优先级

t1.setPriority(5);

t2.setPriority(6);//启动

t1.start();

t2.start();//线程虽然有优先级,但是随机分配的,打印结果不一致

}

}class KeKe extendsThread {public voidrun() {for (int i = 0; i < 10; i++) {

System.out.println(Thread.currentThread().getName()+"----------------"+i);

}

}

}

七、线程休眠

①Thread.sleep()使当前正在执行的线程执行休眠操作(暂停执行) 单位:毫秒

sleep 静态方法 作用: 阻塞当前线程,腾出CPU,让给其他线程

public classThreadTest05 {public static voidmain(String[] args) {

Thread thread= newArray1();

thread.setName("thread1");

thread.start();//获取当前线程的对象 main主线程

Thread t =Thread.currentThread();//获取当前线程的名字

System.out.println("当前名称的名称"+t.getName());//当前名称的名称main//阻塞主线程

for (int i = 0; i < 10; i++) {

System.out.println(Thread.currentThread().getName()+ "-------------------:" +i);try{

Thread.sleep(2000);//程序休眠2秒钟

} catch(InterruptedException e) {//TODO Auto-generated catch block

e.printStackTrace();

}

}

}

}class Array1 extendsThread {public voidrun() {

System.out.println("线程正在启动=-====");for (int i = 0 ; i < 5 ; i ++) {

System.out.println(Thread.currentThread().getName()+ "-------------------:" +i);try{

Thread.sleep(2000);//程序休眠2秒钟

} catch(InterruptedException e) {//TODO Auto-generated catch block

e.printStackTrace();

}

}

}

}

②Thread.yield()暂停当前正在执行的线程对象,并执行其他线程。

1.静态方法

2.作用:给同一个优先级的线程让位,但是让位时间不固定

3.和sleep方法相同,就是yield的时间不固定

他与sleep类似,只是不能由用户执行暂停时间,并且yield()只能让同优先级的线程有执行的机会

packagecom.steven.demo;public classThreadTest07 {public static voidmain(String[] args) {//1.创建线程

Thread thread = newHThread();

thread.setName("线程07");//2.启动线程

thread.start();//3.主线程

for (int i = 0; i < 10; i++) {

System.out.println(Thread.currentThread().getName()+"---------:"+i);

}

System.out.println("Steven=====");

}

}class HThread extendsThread {public voidrun() {for (int i = 0; i < 10; i++) {

System.out.println(Thread.currentThread().getName()+"---------:"+i);if (i % 2 == 0) {//暂定当前线程,执行其他线程

Thread.yield();

}

}

}

}

③线程的基本操作

/*线程的基本操作:创建,启动,休眠,异常处理*/

public classThreadTest06 {public static voidmain(String[] args) {try{//1.创建线程

Thread thread = newMyThread();

thread.setName("线程");//2.启动线程

thread.start();//3.休眠

Thread.sleep(2000);

System.out.println("Steven=====");

}catch(InterruptedException e) {

e.printStackTrace();

}

}

}class MyThread extendsThread {public voidrun() {for (int i = 0; i < 10; i++) {try{

Thread.sleep(3000);

}catch(Exception e) {

e.printStackTrace();

}

System.out.println(Thread.currentThread().getName()+"---------:"+i);

}

}

}

八、线程的合并(join)

public classThreadTest08 {public static voidmain(String[] args) {try{//1.创建线程

Thread thread = newKThread();

thread.setName("线程07");//2.启动线程

thread.start();//3.合并线程 (线程07和main线程合并)

thread.join();//输出只保证一个线程正在执行,依次执行,单线程的程序 (先执行线程07后执行main)//主线程

for (int i = 0; i < 10; i++) {

System.out.println(Thread.currentThread().getName()+"---------:"+i);

}//当前线程可以调用第一个线程的join方法,调用后当前线程会被阻塞不再执行,直到被调用的线程执行完毕,当前线程才会执行

} catch(InterruptedException e) {//TODO Auto-generated catch block

e.printStackTrace();

}

}

}class KThread extendsThread {public voidrun() {for (int i = 0; i < 10; i++) {try{

Thread.sleep(2000);

System.out.println(Thread.currentThread().getName()+"---------:"+i);

}catch(InterruptedException e) {//TODO Auto-generated catch block

e.printStackTrace();

};

}

}

}

九、线程同步案例

<1>模拟取款:(不使用同步机制)多线程同时对同一个账号进行取款操作

/*模拟取款:不使用同步机制,多线程同时对同一个账号进行取款操作

thread 和 thread2

异步编程模型:thread线程执行的是thread , thread2线程执行的是thread2 ,两个线程之间谁也不等于谁

同步编程模型:thread线程和thread2线程执行,当thread线程必须等thread2的线程的执行结果之后,thread线程才能执行 ,这是同步编程

什么时候需要引入同步:

1.为了数据安全,尽管程序的使用率低,但是为了保证数据安全性,必须得加入线程同步机制, 线程同步机制 使程序变成了单线程(一个线程)

2.在什么条件下需要使用线程同步

<1>必须是多线程环境

<2>多线程环境在共享同一个数据时

<3>共享的数据涉及到修改操作*/

packagecom.steven.demo;public classThreadTest09 {public static voidmain(String[] args) {//创建一个公共的账户

Account account = new Account("steven_kou",10000.0);//创建线程对同一个账户进行取款

Thread thread = new Thread(newMoney(account));

thread.setName("steven");

Thread thread2= new Thread(newMoney(account));

thread2.setName("kou");

thread.start();

thread2.start();

}

}//取款线程

class Money implementsRunnable {//账户

Account account;

Money (Account account){this.account =account;

}public voidrun() {

account.withDraw(2000.0);

System.out.println("取款2000.0$,余额为:"+account.getBalance());//取款2000.0$,余额为:8000.0 (输出两次)

}

}//银行账户

classAccount {privateString actno;private double balance;//账户余额

publicAccount() {}public Account(String actno,doublebalance) {this.actno = actno;//成员变量|局部变量

this.balance =balance;

}public voidsetActno(String actno) {this.actno =actno;

}publicString getActno() {returnactno;

}public void setBalance(doublebalance) {this.balance =balance;

}public doublegetBalance() {returnbalance;

}//对外提供一个取款方法

public void withDraw(doublemoney) {//对账户进行取款操作

double after = balance -money;//延迟操作

try{

Thread.sleep(2000);

}catch(InterruptedException e) {

e.printStackTrace();//InterruptedException 线程中断下抛出的异常

}this.setBalance(after);//更新账户余额,重新赋值

}

}

<2>模拟取款(同步机制,同步锁synchronized)

①以下程序使用线程同步机制保证数据安全

packagecom.steven.demo;public classThreadTest09 {public static voidmain(String[] args) {//创建一个公共的账户

Account account = new Account("steven_kou",10000.0);//创建线程对同一个账户进行取款

Thread thread = new Thread(newMoney(account));

thread.setName("steven");

Thread thread2= new Thread(newMoney(account));

thread2.setName("kou");

thread.start();

thread2.start();

}

}//取款线程

class Money implementsRunnable {//账户

Account account;

Money (Account account){this.account =account;

}public voidrun() {

account.withDraw(2000.0);

System.out.println("取款2000.0$,余额为:"+account.getBalance());//取款2000.0$,余额为:8000.0 (输出两次)

}

}//银行账户

classAccount {privateString actno;private double balance;//账户余额

publicAccount() {}public Account(String actno,doublebalance) {this.actno = actno;//成员变量|局部变量

this.balance =balance;

}public voidsetActno(String actno) {this.actno =actno;

}publicString getActno() {returnactno;

}public void setBalance(doublebalance) {this.balance =balance;

}public doublegetBalance() {returnbalance;

}//对外提供一个取款方法//TODO 取款 同步

public void withDraw(doublemoney) {/*需要把同步的代码,放到同步的语句块中

thread线程执行到此处,遇到了synchronized 关键字,就会去找this的对象锁 如果找到了this的对象锁,则进入同步语句块 执行程序

当同步语句块代码执行结束的时候,thread线程归还this的对象锁

在thread线程执行同步语句块的过程中,如果thread2线程也执行以下代码。遇到synchronized 关键字,所以去找this对象锁,但是该对象被thread线程持有, 只能等待thread线程使用完以后再解锁this对象锁*/

//同步锁

synchronized (this) {//对账户进行取款操作

double after = balance -money;//延迟操作

try{

Thread.sleep(2000);

}catch(InterruptedException e) {

e.printStackTrace();//InterruptedException 线程中断下抛出的异常

}//更新账户余额,重新赋值

this.setBalance(after);

}

}

}

②synchronized关键字 添加到成员方法上,线程拿走的也是this对象锁

//对外提供一个取款方法//TODO 取款 同步//synchronized关键字 添加到成员方法上,线程拿走的也是this对象锁

public synchronized void withDraw(doublemoney) {/*需要把同步的代码,放到同步的语句块中

thread线程执行到此处,遇到了synchronized 关键字,就会去找this的对象锁 如果找到了this的对象锁,则进入同步语句块 执行程序

当同步语句块代码执行结束的时候,thread线程归还this的对象锁

在thread线程执行同步语句块的过程中,如果thread2线程也执行以下代码。遇到synchronized 关键字,所以去找this对象锁,但是该对象被thread线程持有, 只能等待thread线程使用完以后再解锁this对象锁*/

//同步锁//synchronized (this) {//对账户进行取款操作

double after = balance -money;//延迟操作

try{

Thread.sleep(2000);

}catch(InterruptedException e) {

e.printStackTrace();//InterruptedException 线程中断下抛出的异常

}//更新账户余额,重新赋值

this.setBalance(after);//}

}

三、守护线程

①定义一个用户线程

packagecom.steven.demo;//定义一个用户线程

public classUserThread01 {public static voidmain(String[] args) {

Runnable runnable= newUserTest();

Thread thread= new Thread(runnable, "UserThread");

thread.start();for (int i = 0; i < 10; i++) {

System.out.println(Thread.currentThread().getName()+ "==== " +i);

}

System.out.println("主线程结束---");

}

}class UserTest implementsRunnable {public voidrun() {for (int i = 0; i < 10; i++) {

System.out.println(Thread.currentThread().getName()+ "==== " +i);

}

}

}

②改为守护线程

packagecom.steven.demo;//守护线程//其他所有的用户线程结束,则守护线程退出//守护线程一般都是无限执行的 守护线程最后结束(先执行用户线程)//设置守护线程以后,当前主线程结束后,守护线程并没有把所有的数据输出就结束 也就是说 守护线程是为用户线程服务的,当用户线程全部结束,守护线程会自动化结束

public classUserThread02 {public static voidmain(String[] args) {

Thread thread= newUserTest02();

thread.setName("thread");//将thread这个用户线程 修改为守护线程

thread.setDaemon(true);

thread.start();//主线程

for (int i = 0; i < 10; i++) {

System.out.println(Thread.currentThread().getName()+ "==== " +i);try{

Thread.sleep(1000);

}catch(InterruptedException e) {//TODO Auto-generated catch block

e.printStackTrace();

}

}

System.out.println("主线程结束---");

}

}class UserTest02 extendsThread {public voidrun() {int i = 0;while (true) {

i++;

System.out.println(Thread.currentThread().getName()+"====:"+i);try{

Thread.sleep(2000);

}catch(InterruptedException e) {

e.printStackTrace();

}

}

}

}

四、定时器简单使用:

packagecom.steven.demo;importjava.text.ParseException;importjava.text.SimpleDateFormat;importjava.util.Date;importjava.util.Timer;importjava.util.TimerTask;/*Timer 定时器*/

public classTimerTest01 {public static voidmain(String[] args) {

System.out.println("来了");

Timer timer= newTimer();try{

Date date= new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse("2018-10-07 19:26:02");//安排在指定的时间执行指定的任务

timer.schedule(new MyTimer(), date,1000*60*60*24);//date执行后续任务的时间间隔 设置定时任务:在2018-10-07 19:26:02执行此任务, 24小时执行一次//timer.schedule(new MyTimer(), date,1000*2);//如果设置每天执行一次:Date date = new SimpleDateFormat("HH:mm:ss").parse("19:26:02");

}catch(ParseException e) {

e.printStackTrace();

}catch(NullPointerException e) {

e.printStackTrace();

}catch(IllegalArgumentException e) {

e.printStackTrace();

}catch(IllegalStateException e) {

e.printStackTrace();

}

}

}class MyTimer extendsTimerTask {public voidrun() {

System.out.println("=="+new Date());//==Sun Oct 07 19:26:02 CST 2018

}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值