Java第20天~第21天/12.2~12.3
来源:互联网 发布:linux ssh2 编辑:程序博客网 时间:2024/05/24 04:45
day20
一、多线程实现的第一种方式:继承Thread类
1、多线程的实现方式一:继承Thread类
* 1)自定一个类:MyThread 继承自Thread类
* 2)在MyThread类中重写Thread类中的run()
* 3)在主线程中,创建该类的实例对象,启动线程
package org.westos_02_实现多线程第一种方式_继承Thread;/** * 多线程程序实现方式1: * 1)自定一个类:MyThread 继承自Thread类 * 2)在MyThread类中重写Thread类中的run() * 3)在主线程中,创建该类的实例对象,启动线程 * @author 小鑫 */public class ThreadDemo { public static void main(String[] args) { //创建该线程的实例对象 MyThread t1 = new MyThread(); //启动线程 //t.run(); //启动线程不是调用run()方法,run()方法只是一个普通的方法,并不会出现线程随机性 //启动线程用的是start()方法,通过JVM调用线程中的run()来进行多个线程抢占cpu执行权 t1.start(); //t.start();//java.lang.IllegalThreadStateException //同一个对象线程只能启动一次,第二次报异常:非法线程状态异常 MyThread t2 = new MyThread(); t2.start(); }}class MyThread extends Thread{ @Override public void run() { for (int x = 0; x < 100; x++) { System.out.println("hello" + x); } }}
2、获取多线程名称
package org.westos_03_获取多线程名称;/** * public final String getName()返回该线程的名称。 * public final void setName(String name)改变线程名称,使之与参数 name 相同。 * public static Thread currentThread():表示正在运行的线程 * @author 小鑫 * */public class ThreadDemo { public static void main(String[] args) { //无参构造形式 //wuCan(); //有参构造 youCan(); } private static void youCan() { //有参构造方式 //创建线程类实例 MyThread my1 = new MyThread("王五"); MyThread my2 = new MyThread("赵六"); //启动线程 my1.start(); my2.start(); } private static void wuCan() { //创建线程类的实例 //无参构造方式 MyThread my1 = new MyThread(); MyThread my2 = new MyThread(); //设置名称 //public final void setName(String name) my1.setName("张三"); my1.setName("李四"); //public static Thread currentThread():表示正在运行的线程 //默认所有的子线程的都在主线程中 System.out.println(Thread.currentThread().getName());//main //分别启动线程 my1.start(); my2.start(); }}class MyThread extends Thread{ //无参构造 public MyThread(){ } //有参构造 public MyThread(String name){ super(name); } @Override ////my1和my2子线程都会执行这段代码,两个子线程在互相抢占CPU的执行权 public void run() { for(int x=0;x<100;x++){ System.out.println("hello"+x); } }}
3、线程终止
public final void join() throws InterruptedException等待该线程终止。
package org.westos_04_线程终止_线程暂停_线程优先级;/** * public final void join() throws InterruptedException等待该线程终止。 * 其他线程要等待该线程终止后才能开始运行 * @author 小鑫 */public class JoinDemo { public static void main(String[] args) { //无参构造 //创建线程实例对象 MyJoin mj1 = new MyJoin(); MyJoin mj2 = new MyJoin(); MyJoin mj3 = new MyJoin(); //设置名称 mj1.setName("张三"); mj2.setName("李四"); mj3.setName("王五"); //启动线程 mj1.start(); try { mj1.join(); } catch (InterruptedException e) { // 中断异常 e.printStackTrace(); } mj2.start(); mj3.start(); }}class MyJoin extends Thread{ @Override public void run() { for(int x=0;x<100;x++){ System.out.println(getName()+":"+x); } }}
4、线程的暂停
public static void yield()暂停当前正在执行的线程对象,并执行其他线程。
package org.westos_04_线程终止_线程暂停_线程优先级;/** * public static void yield()暂停当前正在执行的线程对象,并执行其他线程。 * 暂停当前线程执行其他线程,并不保证另一个线程就一定能抢占到CPU的执行权 * 暂停之后,二者重新抢夺CPU执行权 * @author 小鑫 * */public class YieldThreadDemo { public static void main(String[] args) { //创建线程实例对象 //无参构造 MyYieldThread my1 = new MyYieldThread(); MyYieldThread my2 = new MyYieldThread(); //设置名称 my1.setName("张三"); my2.setName("李四"); //启动线程 my1.start(); my2.start(); }}class MyYieldThread extends Thread{ @Override public void run() { for(int x=0;x<100;x++){ System.out.println(getName()+":"+x); //public static void yield():暂停当前线程 Thread.yield(); } }}
5、线程的优先级
public final int getPriority()返回线程的优先级。
package org.westos_04_线程终止_线程暂停_线程优先级;/** * public final int getPriority()返回线程的优先级。 * 默认优先级是5 * java.lang.Thread public static final int MAX_PRIORITY 10 :最大优先级 优先级大的抢占到CPU的执行权大,并不代表就一定能抢到,因为线程的执行具有随机性! public static final int MIN_PRIORITY 1 :最小优先级 public static final int NORM_PRIORITY 5 :默认优先级 * @author 小鑫 * */public class PriorityDemo { public static void main(String[] args) { //有参构造 //创建线程实例对象 MyPaiority mp1 = new MyPaiority("刘备"); MyPaiority mp2 = new MyPaiority("关羽"); MyPaiority mp3 = new MyPaiority("张飞"); //获取优先级 //System.out.println(mp1.getPriority());//5 //System.out.println(mp2.getPriority());//5 //System.out.println(mp3.getPriority());//5 //设置优先级 mp1.setPriority(10); mp3.setPriority(1); //启动线程 mp1.start(); mp2.start(); mp3.start(); }}class MyPaiority extends Thread{ public MyPaiority() { super(); } public MyPaiority(String name) { super(name); } @Override public void run() { for(int x=0;x<100;x++){ System.out.println(getName()+":"+x); } }}
6、线程睡眠
package org.westos_05_线程睡眠_线程停止_守护线程;import java.util.Date;public class SleepDemo { public static void main(String[] args) { //创建线程实例对象 ThreadSleep ts1 = new ThreadSleep(); ThreadSleep ts2 = new ThreadSleep(); ThreadSleep ts3 = new ThreadSleep(); //设置名称 ts1.setName("线程1"); ts2.setName("线程2"); ts3.setName("线程3"); //启动线程 ts1.start(); ts2.start(); ts3.start(); }}class ThreadSleep extends Thread{ @Override public void run() { for(int x=1;x<=30;x++){ System.out.println(getName()+":"+x+",日期:"+new Date()); //睡眠1秒 try { Thread.sleep(1000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }}
7、停止线程和中断线程
public final void stop():强迫线程停止执行
public void interrupt()中断线程。 表示中断线程一种状态
package org.westos_05_线程睡眠_线程停止_守护线程;import java.util.Date;/** * public final void stop():强迫线程停止执行 * public void interrupt()中断线程。 表示中断线程一种状态 * @author 小鑫 * */public class StopDemo { public static void main(String[] args) { //创建线程实例对象 StopThread st = new StopThread(); //启动线程 st.start(); //开始执行Tue Dec 05 20:12:10 CST 2017 //结束执行Tue Dec 05 20:12:15 CST 2017 //三秒睡不醒,停止它 try { Thread.sleep(3000); //st.stop();//中间那条线表示过时了 //开始执行Tue Dec 05 20:11:40 CST 2017 st.interrupt(); //开始执行Tue Dec 05 20:12:55 CST 2017 //线程睡着了 //结束执行Tue Dec 05 20:12:58 CST 2017 //能打印线程睡着了,说明走catch语句,即中断try语句 } catch (InterruptedException e) { e.printStackTrace(); } }}class StopThread extends Thread{ @Override public void run() { System.out.println("开始执行"+new Date()); try { Thread.sleep(5000); } catch (InterruptedException e) { System.out.println("线程睡着了"); } System.out.println("结束执行"+new Date()); }}
8、守护线程
public final void setDaemon(boolean on) on指定true,就是设置守护线程…
将该线程标记为守护线程或用户线程。
package org.westos_05_线程睡眠_线程停止_守护线程;/** * public final void setDaemon(boolean on) on指定true,就是设置守护线程... * 将该线程标记为守护线程或用户线程。 * 当正在运行的线程都是守护线程时,Java 虚拟机退出。 * 该方法必须在启动线程前调用。 * jvm自动退出,对于主线程的数据如果直接输出完毕,对于两个守护线程来说不会立即消失,Jvm等会就自动退出. * @author 小鑫 * */public class DemaonDemo { public static void main(String[] args) { //创建线程实例对象 MyDemaonThread mt1 = new MyDemaonThread(); MyDemaonThread mt2 = new MyDemaonThread(); //设置名称 mt1.setName("守护1"); mt2.setName("守护2"); //设置守护线程 mt1.setDaemon(true); mt2.setDaemon(true); //启动线程 mt1.start(); mt2.start(); //设置被守护线程 Thread.currentThread().setName("被守护线程"); for(int x=0;x<5;x++){ System.out.println(Thread.currentThread().getName()+":"+x); } }}class MyDemaonThread extends Thread{ @Override public void run() { for(int x=0;x<100;x++){ System.out.println(getName()+":"+x); } }}
二、多线程实现的第二种方式:Runnable接口
1、多线程实现的第二种方式:Runnable接口
* 1)自定义一个类MyRunnable,该类实现Runnable接口
* 2)实现该接口中的run()方法
* 3)在主线程中创建该类的实例对象,
* 4)创建Thread类对象,将3)创建的这个对象作为参数进行传递
* 5)分别启动线程
package org.westos_06_实现多线程第二种方式_Runnable接口;/** * 多线程实现的第二种方式:(实际开发中第二种比第一种应用更广泛) * 开发步骤: * 1)自定义一个类MyRunnable,该类实现Runnable接口 * 2)实现该接口中的run()方法 * 3)在主线程中创建该类的实例对象, * 4)创建Thread类对象,将3)创建的这个对象作为参数进行传递 * 5)分别启动线程 * @author 小鑫 * */public class ThreadDemo { public static void main(String[] args) { //创建MyRunnable实例对象 MyRunnable my= new MyRunnable(); //创建线程对象 //public Thread(Runnable target) //Thread t1 = new Thread(my); //Thread t2 = new Thread(my); //public Thread(Runnable target,String name) Thread t1 = new Thread(my, "线程1"); Thread t2 = new Thread(my, "线程2"); t1.start(); t2.start(); }}class MyRunnable implements Runnable{ @Override public void run() { for(int x=0;x<100;x++){ //getName()是Thread类中的方法,间接使用Thread类的静态功能获得线程名称 System.out.println(Thread.currentThread().getName()+":"+x); } }}
2、检验多线程安全问题的标准(以后在判断一个多线程序是否有安全问题的标准)
* 1)当前是否是一个多线程环境
* 2)多线程环境中是否有共享数据
* 3)是否有多条语句对共享数据进行操作
package org.westos_07_模拟多线程_电影院卖票案例;/** * 为了模拟电影院卖票更真实的场景,每一个窗口卖票应该延迟操作 * 在接口自实现类中,在run()方法中让每一个线程执行睡眠0.1秒 * *加入延迟操作: * 1)一张票可能被卖多次 * 100张票会出现多次 * CPU的执行具有原子性操作 * 2)可能出现负票 * 1,0,-1 * 延迟操作和线程随机性导致 * * *这两种情况都属于线程安全问题,现在写的这个代码是一种有问题的代码? * 如何解决多线程的安全问题呢? * 检验多线程安全问题的标准(以后在判断一个多线程序是否有安全问题的标准) * 1)当前是否是一个多线程环境 * 2)多线程环境中是否有共享数据 * 3)是否有多条语句对共享数据进行操作 * *就目前这个电影院卖票这个案例, * 1)是多线程环境,因为要实现3个窗口同时卖票 * 2)有共享数据,比如:tickets * 3)有多条语句对当前这个共享数据进行操作 * *优化改进: * 1)多线程环境和共享数据改变不了,突破口就是3)条件:将多条语句对共享数据的操作进行更改 * * 将多条语句对共享数据进行操作的代码用代码块包起来 * 使用同步代码块:synchronized(同步锁对象){ * 多条语句对共享数据的操作; * } * @author 小鑫 */public class SellTicketDemo { public static void main(String[] args) { //创建线程实例对象 TicketThread tt1 = new TicketThread(); TicketThread tt2 = new TicketThread(); TicketThread tt3 = new TicketThread(); //设置名称 tt1.setName("窗口1"); tt2.setName("窗口2"); tt3.setName("窗口3"); //启动线程 tt1.start(); tt2.start(); tt3.start(); }}class TicketThread extends Thread{ //private int tickets=100; //定义100张票,票被三个线程公用,用static修饰 private static int tickets=100; @Override public void run() { while(true){ try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } if(tickets>0){ System.out.println(getName()+"正在出售第"+(tickets--)+"张票"); } } }}
3、多线程同步机制
package org.westos_08_线程同步机制_电影院卖票案例;/** * 就目前这个电影院卖票这个案例, 1)是多线程环境,因为要实现3个窗口同时卖票 2)有共享数据,比如:tickets * 3)有多条语句对当前这个共享数据进行操作 * * 优化改进: 1)多线程环境和共享数据改变不了,突破口就是3)条件:将多条语句对共享数据的操作进行更改 * * 将多条语句对共享数据进行操作的代码用代码块包起来 Java的同步机制: 使用同步代码块:synchronized(同步锁对象){ * 多条语句对共享数据的操作; } * * 同步锁对象:应该每一个线程都要使用这个锁对象(同步锁):理解为门的开和关 使用同步代码块可以解决线程安全问题 * * @author 小鑫 * */public class SellTicketDemo { public static void main(String[] args) { // 创建TicketThread对象 TicketThread tt = new TicketThread(); // 创建线程对象 Thread t1 = new Thread(tt, "窗口1"); Thread t2 = new Thread(tt, "窗口2"); Thread t3 = new Thread(tt, "窗口3"); // 启动线程 t1.start(); t2.start(); t3.start(); }}class TicketThread implements Runnable { // 定义100张票 private static int tickets = 100; // 设置锁对象,三个线程必须使用同一个锁对象 // 可以是Object类型,任意的Java类 private Object obj = new Object(); @Override public void run() { // 一直邮有票 while (true) { // 睡眠0.1秒 synchronized (obj) { if (tickets > 0) { try { Thread.sleep(100); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + "正在出售第" + (tickets--) + "张票"); } } } }}
4、同步方法
package org.westos_09_线程同步机制_同步方法_电影院卖票案例;/** * 同步方法 * @author 小鑫 */public class SellTeckesDemo { public static void main(String[] args) { // 创建TecketThread对象 TecketThread tt = new TecketThread(); // 创建线程实例对象 Thread t1 = new Thread(tt, "窗口1"); Thread t2 = new Thread(tt, "窗口2"); Thread t3 = new Thread(tt, "窗口3"); // 启动线程 t1.start(); t2.start(); t3.start(); }}class TecketThread implements Runnable { // 定义100张被共用的票,不能修改 private static int tickets = 100; // 创建锁对象 private Object obj = new Object(); private int x; @Override public void run() { while (true) { if (x % 2 == 0) { //静态时的同步锁对象--->类名.class //静态同步方法:要通过反射获取Class类对象(当前类的字节码文件对象) synchronized (TecketThread.class) { if (tickets > 0) { try { //睡眠0.1秒 Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + "正在出售第" + (tickets--) + "张票"); } } } else { //sellTicket(); } } } // 非静态同步方法,锁对象是this /*private synchronized void sellTicket() { if (tickets > 0) { // 设置线程睡眠0.1秒 try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + "正在出售第" + (tickets--) + "张票"); } }*/ //静态同步方法,锁对象是(类名.class) private static synchronized void sellTicket() { if (tickets > 0) { // 设置线程睡眠0.1秒 try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + "正在出售第" + (tickets--) + "张票"); } }}
day21
一、同步锁
1、Lock锁
* Jdk5以后Java提供了一个更具体的锁对象:Lock Lock 实现提供了比使用 synchronized 方法和语句可获得的更广泛的锁定操作
* Lock是一个接口,所以它在使用的是 ReentrantLock子实现类
* public void lock()获取锁。
package org.westos_01_Lock锁;import java.util.concurrent.locks.Lock;import java.util.concurrent.locks.ReentrantLock;/** * public void lock()获取锁。 * public void unlock()试图释放此锁 * * @author 小鑫 */public class SellTicketDemo { public static void main(String[] args) { // 创建TicketThread对象 TicketThread tt = new TicketThread(); // 创建线程实例对象 Thread t1 = new Thread(tt, "窗口1"); Thread t2 = new Thread(tt, "窗口2"); Thread t3 = new Thread(tt, "窗口3"); // 启动线程 t1.start(); t2.start(); t3.start(); }}class TicketThread implements Runnable { // 定义100张票 private static int tickets = 100; // 锁对象 private Object obj = new Object(); // 定义一个具体锁对象 private Lock l = new ReentrantLock(); @Override public void run() { // oldMethod(); // 一直有票 while (true) { // 获取锁 try { l.lock(); if (tickets > 0) { // 睡眠0.1秒 try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + "正在出售第" + (tickets--) + "张票"); } } finally{ //释放锁对象 l.unlock(); } } } private void oldMethod() { // 一直有票 while (true) { synchronized (obj) { if (tickets > 0) { // 睡眠0.1秒 try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + "正在出售第" + (tickets--) + "张票"); } } } }}
2、死锁现象
* 死锁线程:两个或者两个以上的线程出现了互相等待的情况,就会出现死锁!
package org.westos_02_死锁;/** * 使用同步机制可以解决多线程的安全问题,但是自身也会有弊端: * 1)同步---->执行效率低(每一个线程在抢占到CPU的执行权,会去将(门)关闭,别的线程进不来) * 2)容易出现死锁现象 * @author 小鑫 */public class DieLockDemo { public static void main(String[] args) { //创建线程对象 DieLock dl1 = new DieLock(true); DieLock dl2 = new DieLock(false); //启动线程 dl1.start(); dl2.start(); }}class MyLock{ //创建两把锁对象 public static final Object objA = new Object(); public static final Object objB = new Object();}class DieLock extends Thread{ //定义一个成员变量 private boolean flag; public DieLock(boolean flag){ this.flag=flag; } @Override public void run() { if(flag){ synchronized(MyLock.objA){ System.out.println("if objA"); synchronized (MyLock.objB) { System.out.println("if objB"); } } }else{ synchronized(MyLock.objB){ System.out.println("else objB"); synchronized(MyLock.objA){ System.out.println("else objA"); } } } }}
3、生产者消费者模式
package org.westos_03_生产者消费者模式;/** * * @author 小鑫 */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); Thread t2 = new Thread(gt); //启动线程 t1.start(); t2.start(); }}//资源对象类class Student{ String name; int age;}//生产者类class SetThread implements Runnable{ private Student s; public SetThread(Student s){ this.s=s; } @Override public void run() { //设置资源数据 s.name="张三"; s.age=30; }}//消费者类class GetThread implements Runnable{ private Student s; public GetThread(Student s){ this.s=s; } @Override public void run() { System.out.println(s.name+"---"+s.age); }}
4、同步机制生产者消费者模式
package org.westos_04_同步生产者消费者模式;/** * * @author 小鑫 */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); Thread t2 = new Thread(gt); //启动线程 t1.start(); t2.start(); }}// 学生资源对象类class Student { String name; int age;}// 生产者线程class SetThread implements Runnable { private Student s; public SetThread(Student s) { this.s = s; } private int x; @Override public void run() { // 同步机制 while (true) { synchronized (s) { if (x % 2 == 0) { s.name = "张三"; s.age = 30; } else { s.name = "李四"; s.age = 40; } x++; } } }}//消费者线程class GetThread implements Runnable{ private Student s; public GetThread(Student s){ this.s=s; } @Override public void run() { while(true){ synchronized (s) { System.out.println(s.name + "---" + s.age); } } }}
5、同步机制等待唤醒机制生产者消费者模式
package org.westos_05_同步机制_等待唤醒机制_生产者消费者模式;/** * * @author 小鑫 */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); Thread t2 = new Thread(gt); //启动线程 t1.start(); t2.start(); }}//资源对象学生类class Student{ String name; int age; //声明标记 boolean flag;//默认没有数据,如果true,则说明有数据}//生产者线程class SetThread implements Runnable{ private Student s; public SetThread(Student s){ this.s=s; } private int x; @Override public void run() { while(true){ //同步机制 synchronized(s){ //判断是否有数据 /** * 如果生产者先抢到CPU执行权,判断是否有数据 * 如果没有数据,则释放锁对象,生产数据; * 如果有数据了,修改标记,通知消费者消费数据,唤醒等待状态 */ if(s.flag){ //等待 try { s.wait();//阻塞式方法,立即释放锁 } catch (InterruptedException e) { e.printStackTrace(); } } if(x%2==0){ s.name="张三"; s.age=30; }else{ s.name="李四"; s.age=40; } x++; //修改标记 s.flag=true; //有数据了,通知t2消费者线程来消费数据 //唤醒等待这种状态 s.notify(); } } } }//消费者线程class GetThread implements Runnable{ private Student s; public GetThread(Student s){ this.s=s; } @Override public void run() { while(true){ synchronized(s){ //判断是否有数据 /** * 消费者先抢到CPU执行权,判断是否有数据,如果有数据则输出; * 如果没有数据,立即释放锁对象,并修改标记,通知生产者生产数据,唤醒等待状态 */ if(!s.flag){ try { s.wait();//调用时立即释放锁 } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println(s.name+"---"+s.age); //修改标记 s.flag=false; //通知t1生产者线程,没有数据了,该生产数据了 //唤醒t1线程 s.notify(); } } }}
6、最终版生产者消费者模式
package org.westos_06_最终版_生产者消费者模式;/** * 最终版代码: * 现在将资源对象Student中的成员变量私有化 * 并且给当前类中提供两个方法,同步方法 * 在两个线程:生产者线程和消费者中线程,注意调用这两个方法就可以了! * @author 小鑫 * */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); Thread t2 = new Thread(gt); //启动线程 t1.start(); t2.start(); }}class Student{ private String name; private int age; //声明一个变量 private boolean flag; //默认没有数据 //set(String name,int age)方法,产生数据数据 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; //有数据了,通知消费者线程 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();//唤醒生产者线程 }}//生产者线程class SetThread implements Runnable{ private Student s; public SetThread(Student s){ this.s=s; } private int x; @Override public void run() { while(true){ if(x%2==0){ s.set("张三", 30); }else{ s.set("李四", 40); } x++; } }}//消费者线程class GetThread implements Runnable{ private Student s; public GetThread(Student s){ this.s=s; } @Override public void run() { while(true){ s.get(); } }}
二、线程组
- 线程组表示一个线程的集合:Java允许一个线程中有多个线程
package org.westos_07_线程组;/** * 线程组表示一个线程的集合:Java允许一个线程中有多个线程 * @author 小鑫 */public class ThreadGroupDemo { public static void main(String[] args) { //获取线程组名称 //method1(); //设置线程组名称 method2(); } //设置线程组名称 private static void method2() { //public ThreadGroup(String name)构造一个新线程组 ThreadGroup tg = new ThreadGroup("新线程"); //创建资源对象 MyRunnable my = new MyRunnable(); //public Thread(ThreadGroup group,Runnable target ,String name){} //创建线程类对象,并且将线程组对象作为参数进行传递 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()); } //获取线程组名称 private static void method1() { //创建资源对象 MyRunnable my = new MyRunnable(); //创建线程对象 Thread t1 = new Thread(my); Thread t2 = new Thread(my); //启动线程 //t1.start(); //t2.start(); //获取线程组对象 //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);//main System.out.println(name2);//main //所以线程默认线程组名称是main System.out.println(Thread.currentThread().getThreadGroup().getName()); }}class MyRunnable implements Runnable { @Override public void run() { for (int x = 0; x < 100; x++) { System.out.println(Thread.currentThread().getName() + ":" + x); } }}
三、多线程实现的第三种方式
1、Executors工厂类产生线程池
package org.westos_08_线程池;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;/** * 多线程程序的实现方式3: * Executors工厂类来产生线程池 public static ExecutorServicenewFixedThreadPool(int nThreads) Executors工厂类中的这个方法参数直接指定在当前线程池中有多少个线程 * 方法的返回值是ExecutorService对象,该对象表示一个线程池 ExecutorsService : * 接口中的方法 Future<?>submit(Runnable task) <T> Future<T> submit(Callable<T> task) * @author 小鑫 */public class ExecutorsDemo { public static void main(String[] args) { //创建线程对象,使用Executors工厂类 //public static ExecutorService newFixedThreadPool(int nThreads) ExecutorService pool = Executors.newFixedThreadPool(2); //使用ExecutorsService(跟着多个异步任务)方法 //submit(Runnable task) pool.submit(new MyRunnable()); pool.submit(new MyRunnable()); //结束线程池 pool.shutdown(); //pool-1-thread-1:x //pool-1-thread-2:x }}class MyRunnable implements Runnable { @Override public void run() { for (int x = 0; x < 100; x++) { System.out.println(Thread.currentThread().getName() + ":" + x); } }}
2、Callable接口
package org.westos_08_线程池;import java.util.concurrent.Callable;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;/** * ExecutorsService :接口中的方法 * <T> Future<T> submit(Callable<T> task) * 该返回值表示:异步计算的结果! * @author 小鑫 */public class CallableDemo { public static void main(String[] args) { //创建线程对象,工厂类 ExecutorService Threadpool = Executors.newFixedThreadPool(2); //提交Callable任务(异步任务) Threadpool.submit(new MyCallable()); Threadpool.submit(new MyCallable()); //结束线程 Threadpool.shutdown(); //pool-1-thread-1:x //pool-1-thread-2:x }}class MyCallable implements Callable<Object>{ @Override public Object call() throws Exception { for(int x=0;x<100;x++){ System.out.println(Thread.currentThread().getName()+":"+x); } return null; }}
3、Callable接口求和
package org.westos_09_线程池Callable求和;import java.util.concurrent.Callable;import java.util.concurrent.ExecutionException;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import java.util.concurrent.Future;public class CallableDemo2 { public static void main(String[] args) throws InterruptedException, ExecutionException { //创建线程对象,工厂类 ExecutorService Threadpool = Executors.newFixedThreadPool(2); //提交两个异步任务,计算1-100,1-200的和 Future<Integer> f1 = Threadpool.submit(new MyCallable(100)); Future<Integer> f2 = Threadpool.submit(new MyCallable(200)); //分别调用Future接口中 get()方法,返回具体的结果 Integer i1 = f1.get(); Integer i2 = f2.get(); System.out.println("1-100的和是:"+i1); System.out.println("1-200的和是:"+i2); //1-100的和是:5050 //1-200的和是:20100 }}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=1;x<=number;x++){ sum += x; } return sum; }}
4、多线程匿名内部类
多线程中匿名内部类的方式
* new 类名(具体类,抽象类),接口{
* 重写/实现方法;
* }
匿名内部类本质:
* 继承该类或者实现该接口的子类对象
package org.westos_09_线程池Callable求和;/** * 多线程中匿名内部类的方式 * new 类名(具体类,抽象类),接口{ * 重写/实现方法; * } * 匿名内部类本质: * 继承该类或者实现该接口的子类对象 * @author 小鑫 */public class ThreadDemo { public static void main(String[] args) { //继承Thread类 new Thread(){ @Override public void run(){ for(int x=0;x<100;x++){ System.out.println(getName()+":"+x); } } }.start(); //Runnable接口 new Thread(new Runnable(){ @Override public void run(){ for(int x = 0 ; x < 100 ; x ++){ System.out.println(Thread.currentThread().getName()+":"+x); } } }).start(); new Thread(new Runnable(){ @Override public void run() { for(int x = 0 ; x <100 ; x ++){ System.out.println("hello"+x); } } }){ @Override public void run() { for(int x = 0 ; x <100 ; x ++){ System.out.println("world"+x); } } }.start(); }}
四、定时器Timer
定时器: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()终止此计时器,丢弃所有当前已安排的任务
1、 public void schedule(TimerTask task, long delay)在多少毫秒后执行指定任务
package org.westos_10_定时器Timer;import java.util.Timer;import java.util.TimerTask;/** * 需求:3秒后执行爆炸任务 * @author 小鑫 */public class TimerDemo { public static void main(String[] args) { //创建计时器 Timer t = new Timer(); //public void schedule(TimerTask task, long delay)在多少毫秒后执行指定任务 t.schedule(new MyTask(t), 3000); }}class MyTask extends TimerTask{ private Timer t; public MyTask(){ } public MyTask(Timer t){ this.t=t; } @Override public void run() { System.out.println("boom..."); t.cancel();//取消任务 }}
2、安排在指定的时间执行指定的任务
package org.westos_10_定时器Timer;import java.util.Timer;import java.util.TimerTask;/** * public void schedule(TimerTask task, long delay, long period) * 在多少毫秒后,执行任务,并且每个多少毫秒重复执行 * * 需求:3秒后执行爆炸任务,每隔2秒重复爆炸 * @author 小鑫 */public class TimerDemo2 { public static void main(String[] args) { //创建计时器 Timer t = new Timer(); t.schedule(new MyTask2(), 3000, 2000); }}class MyTask2 extends TimerTask{ @Override public void run() { System.out.println("boom..."); }}
3、在指定的时间删除我们的指定目录
package org.westos_10_定时器Timer;import java.io.File;import java.text.ParseException;import java.text.SimpleDateFormat;import java.util.Date;import java.util.Timer;import java.util.TimerTask;/** * 需求:在指定的时间删除我们的指定目录 * @author 小鑫 */public class TimerTest { public static void main(String[] args) throws ParseException { //创建定时器 Timer t = new Timer(); //指定删除日期 String s="2017-12-8 10:40:00"; //创建SimpleDateFormat对象 SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); Date date = sdf.parse(s); //public void schedule(TimerTask task,Date time)安排在指定的时间执行指定的任务 t.schedule(new DeleteFolder(), date); }}class DeleteFolder extends TimerTask{ @Override public void run() { File srcFolder = new File("demo"); deleteFolder(srcFolder); } private void deleteFolder(File srcFolder) { //获取srcFolder文件及文件夹数组 File[] fileArray = srcFolder.listFiles(); //非空判断 if(fileArray!=null){ for(File file:fileArray){ //判断是否是文件夹 if(file.isDirectory()){ //递归删除,回到该方法 deleteFolder(file); }else{ //不是文件夹,直接删除 System.out.println(file.getName()+"---"+file.delete()); } } System.out.println(srcFolder.getName()+"---"+srcFolder.delete()); } }}
五、IO流存入文件注册登录案例
用户实体类
package org.westos_11_User;/** * 用户实体 * @author 小鑫 * */public class User { private String username; private String password; public User(){ } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; }}
注册登录接口
package org.westos_11_User;public interface UserDao { /** * 用户登录功能 * * @param username * 登录输入的用户名 * @param password * 登录输入的密码 * @return * 返回是否登录成功 */ public abstract boolean isLogin(String username, String password); /** * 用户注册功能 * @param user */ public abstract void regist(User user);}
用户操作接口实现类
package org.westos_11_User;import java.io.BufferedReader;import java.io.BufferedWriter;import java.io.File;import java.io.FileNotFoundException;import java.io.FileReader;import java.io.FileWriter;import java.io.IOException;/** * 用户操作接口实现类 * @author 小鑫 * */public class UserDaoImpl implements UserDao { //File对象封装文件 private static File file=new File("user.txt"); static{ try { file.createNewFile(); } catch (IOException e) { System.out.println("文件创建失败"); } } //登录功能 @Override public boolean isLogin(String username, String password) { //定义标记 boolean flag=false; //创建字符输入流 BufferedReader br=null; try { br=new BufferedReader(new FileReader(file)); //一次读一行 String line=null; while((line=br.readLine())!=null){ String[] s = line.split("="); if(s[0].equals(username) && s[1].equals(password)){ //登录成功,修改标记 flag=true; } } } catch (FileNotFoundException e) { System.out.println("登录时找不到文件导致失败"); } catch (IOException e) { System.out.println("用户登录失败"); }finally{ //释放资源 if(br!=null){ try { br.close(); } catch (IOException e) { System.out.println("释放资源失败"); } } } return flag; } //注册功能 @Override public void regist(User user) { //注册使用字符缓冲输出流 BufferedWriter bw=null; try { bw=new BufferedWriter(new FileWriter(file ,true)); //固定一种格式 bw.write(user.getUsername()+"="+user.getPassword()); bw.flush(); bw.newLine(); } catch (IOException e) { System.out.println("用户注册失败"); }finally{ //针对流对象非空判断 if(bw!=null){ try { bw.close(); } catch (IOException e) { System.out.println("用户注册释放资源失败"); } } } }}
用户测试类
package org.westos_11_User;import java.util.Scanner;/** * 用户测试类 * @author 小鑫 * */public class UserTest { public static void main(String[] args) { while(true){ //选择界面 System.out.println("--------欢迎光临--------"); System.out.println("1 注册"); System.out.println("2 登录"); System.out.println("3 退出"); //创建键盘录入对象 Scanner sc = new Scanner(System.in); //调用功能 UserDaoImpl ud = new UserDaoImpl(); System.out.println("请选择"); String choice = sc.nextLine(); switch(choice){ case "1": //注册界面 System.out.println("------注册界面------"); System.out.println("请输入用户名"); String newUsername = sc.nextLine(); System.out.println("请输入密码"); String newPassword = sc.nextLine(); //创建用户对象,封装用户名和密码 User u = new User(); u.setUsername(newUsername); u.setPassword(newPassword); //调用东功能 ud.regist(u); System.out.println("恭喜您,注册成功"); break; case "2": //登陆界面 System.out.println("------登陆界面------"); System.out.println("请输入用户名:"); String username = sc.nextLine() ; System.out.println("请输入密码:"); String password = sc.nextLine() ; //调用功能 boolean flag = ud.isLogin(username, password); if(flag){ System.out.println("登录成功"); System.exit(0); }else{ System.out.println("登录失败,用户名或密码不正确"); } break; case "3": //退出界面 System.out.println("谢谢使用,欢迎下次光临"); System.exit(0); break; } } }}
- Java第20天~第21天/12.2~12.3
- java基础第21天
- java学习第21天
- java基础第20天
- java学习第20天
- Java第5天
- java第7天
- java第11天
- java第12天
- java-第5天
- java笔记(多线程+包)-第21天
- 华恩JAVA班第21天
- java初级第20天总结笔记
- 华恩JAVA班第20天
- java 第3天笔记
- java 第4天笔记
- java基础第1天
- java基础第2天
- java
- Codeforces Round #441 (Div. 2, by Moscow Team Olympiad) F. High Cry
- IO流作业
- chrome input 的背景黄色
- GYM
- Java第20天~第21天/12.2~12.3
- pyqt5 播放音乐加切换图片
- java中的代理
- 在linux上使用Jmeter进行压力测试
- 文章标题
- [LOJ2267][SDOI2017]龙与地下城-FFT-自适应辛普森积分
- 一位程序员工作10年总结的13个忠告
- 构造器参数列表的注意事项
- Docker网络配置