多线程三种实现方式/IO流模拟用户注册及登录

一:多线程:一个程序中有多条进程;

         单线程:一个程序中有一条进程

#java虚拟机是多线程程序吗?

是多线程程序,因为JAVA虚拟机中有垃圾回收器,该作用是为了防止内存溢出;当调用程序的时候,至少会开启两条进程,首先会开启main主线程,然后会调用垃圾回收器,回收掉不用的成员变量和没有更对引用的对象;

二:如何实现多线程程序:

要想实现多线程程序,就必须要创建一个进程,而创建进程,就需要调用系统资源创建,JAVA语言中不会调用系统资源进行创建进程,但是C/C++可以,所以JAVA语言是间接通过C/C++调用系统资源创建进程来实现多线程的程序

三:多线程程序的实现方式一:

1.     自定义资格类,该类继承自Thread类

2.     在该类中重写run()方法

3.     在当前类(主线程类)中创建该类的实例化对象

#使用继承的方式实现多线程的启动

扫描二维码关注公众号,回复: 2664056 查看本文章

package ThreadText;

/**

 * 需求:使用继承的方法来实现多线程程序

 * */

public class ThreadText_01 {

    public static void main(String[] args) {

       MyThread my1=new MyThread();//创建子实现类的对象

       MyThread my2=new MyThread();

      

       my1.setName("线程一");

       my2.setName("线程二");

      

       //启动线程

       my1.start();

       my2.start();

      

    }

}

class MyThread extends Thread{

    public void run(){//重写thread类中的run()方法

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

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

       }

    }

}


#注意:

(1)该方法在启动线程的时候调用的是start()方法,二不是run()方法,调用start()方法的实质就是通过JAVA虚拟机调用run()方法

(2)   该多线程一旦被启动,就不能再次调用

(3)   由于该类中原本就有getName()方法,所以在子实现类中应该避免定义name成员,同时避免该类中采用getName()方法调用该成员名字;该方法是用来获取当前线程的名称

四:Thread类中的成员方法:

1.     线程终止:

public final void join()等待该线程终止。(该方法是在启动该线程之后执行)该方法会跑出异常: throws InterruptedException

2.     返回线程的优先级:

public final int getPriority()返回线程的优先级。

public static final int MAX_PRIORITY 10  :最大优先级(优先级大的抢占到CPU的执行权大,并不代表就一定能抢到,因为线程的执行具有随机性!)

public static final int MIN_PRIORITY 1   :最小优先级

public static final int NORM_PRIORITY 5  :默认优先级

3.     暂停线程:

public static void yield()暂停当前正在执行的线程对象,并执行其他线程。暂停当前线程执行其他线程,并不保证另一个线程就一定能抢占到CPU的执行权

#多线程的join(),yield()和 getPriority()方法的综合应用:

package ThreadText;

/**

 *需求:使用Thread类的join(),yield() getPriority()方法执行多线程程序

 * */

public class ThreadText_02 {

    public static void main(String[] args) {

       Mythread my1=new Mythread();

       Mythread my2=new Mythread();

      

       my1.setName("线程一");

       my2.setName("线程二");

      

       my1.setPriority(10);//将线程一的优先级设置为最大

       my2.setPriority(1);//将线程二的优先级设置为最小

      

       my1.start();//启动线程一

       try {

           my1.join();

       } catch (InterruptedException e) {

           System.out.println("这里终止了线程一");

//         e.printStackTrace();

       }//终止该线程

       my2.start();

    }

}

class Mythread extends Thread{

    public void run(){

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

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

           Thread.yield();//终止当前正在运行的线程

       }

    }

}


4.  线程停止:

public final void stop():强迫线程停止执行

public void interrupt()中断线程。 表示中断线程一种状态

5.     线程睡眠

public staticvoid sleep(long millis) 在指定的毫秒数内让当前正在执行的线程休眠(暂停执行;该方法会跑出异常: throws InterruptedException

#使用Thread类的sleep()方法,进行执行多线程程序:

package ThreadText;

/**

 * 需求:使用多线程的stop()方法和sleep()方法执行多线程程序

 * */

public class ThreadText_03 {

    public static void main(String[] args) {

       MyThread1 my1=new MyThread1();

       MyThread1 my2=new MyThread1();

      

       my1.setName("线程一");

       my2.setName("线程二");

      

       //启动线程

       my1.start();

       //给线程一添加睡眠时间

      

      

    }

}

class MyThread1 extends Thread{

    public void run(){

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

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

           try {

              Thread.sleep(3000);

           } catch (InterruptedException e) {

              System.out.println("此方法是对线程调用睡眠模式");

//            e.printStackTrace();

           }

       }

    }

}


6.     守护线程

public final void setDaemon(boolean on)  on指定true,就是设置守护线程...

将该线程标记为守护线程或用户线程。当正在运行的线程都是守护线程时,Java 虚拟机退出。

#使用守护线程执行多线程程序:

package ThreadText;

/**

 * 需求:使用守护线程执行多线程程序

 * 1.自定义一个类,该类继承自Thread,

 * 2.在该类中重写run()方法

 * 3.在主线程中,创建两个子实现类的对象,

 * 4.调用setName()方法,分别给两个子线程命名为关羽和张飞,

 * 5.Thread类调用currentThread()方法再调用setName()方法,将主线程的名称改为刘备

 * 6.在主线程和子实现类中分别定义for循环来获取每个线程的名称

 * */

public class ThreadText_04 {

    public static void main(String[] args) {

       MyThread2 my1=new MyThread2();

       MyThread2 my2=new MyThread2();

      

       my1.setName("关羽");

       my2.setName("张飞");

       //设置守护线程

       my1.setDaemon(true);

       my2.setDaemon(true);//该方法中的参数设置为true表示设置为守护线程

      

       //启动线程

       my1.start();

       my2.start();

      

       //通过Thread类给获取主线程的名称,并且给其命名

       Thread.currentThread().setName("刘备");

       //定义一个for循环,来遍历主线程的同时获取每一个子线程的名称

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

           System.out.println(Thread.currentThread().getName() + "--" + i);//主线程结束后,子线程并不会立即释放,

       }

      

    }

}

class MyThread2 extends Thread{

    public void run(){

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

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

       }

    }

}


五: 多线程实现的第二种方式(该方法使用接口的形式)

1.开发步骤

(1)自定义一个类,该类实现接口Runnable接口

(2)在该类中重写接口中的run()方法

(3)在主线程中创建子实现类的实例化对象

(4)在创建Thread类的对象,同时将上述的对象当做参数进行传递

(5)分别启动线程

         #用接口的方法执行多线程程序:

package ThreadText_02;

/**

 * 需求:使用自定义类实现接口的方法来执行多线程程序

 * */

public class ThreadText_01 {

    public static void main(String[] args) {

       MyThread my=new MyThread();//创建自定义类的对象

      

       //创建Thread类的对象

       Thread t1=new Thread(my,"线程一");//该方法的第二个参数指明线程的名称

       Thread t2=new Thread(my,"线程二");

      

       //启动线程

       t1.start();

       t2.start();

    }

}

class MyThread implements Runnable{

 

    public void run() {

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

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

       }

      

    }

}


#在此执行多线程程序中,获取线程名称的方法使用Thread.currentThread().getName()方法来获取当前线程的名称

六:多线程的线程安全问题:

1.  检验多线程安全问题的标准

(1)   当前是否是一个多线程环境

(2)   多线程中是否有共享数据

(3)   是否有多条语句对共享数据进行操作

2.     对于多线程程序,加入延迟操作会出现线程安全问题

#对于多线程问题加入延迟操作,可能会出现的问题(电影院售票案例)

1)     一张票可能被卖多次

2)     可能会出现负数

这是由于多线程的延迟操作和线程随机性导致的

package ThreadText_02;

/**

 * 需求:使用自定义类实现接口的形式来实现电影院卖票:

 * 1.创建自定义类MyThread2,该类实现接口Runnable

 * 2.在该方法中定义一个成员变量tickles=100

 * 3.定义一个while循环,模拟电影院一直有票

 * 4.再加入睡眠时间1,

 * 5.在主线程中创建该类的实例化对象

 * 6.再创建Thread类的三个对象,共同将上述的对象当做参数传入该方法中,再分别定义三个线程的名称为窗口1,2,3

 * 7.启动线程,最后输出窗口出票情况

 * */

public class ThreadText_02 {

    public static void main(String[] args) {

       myThread my=new myThread();

      

       Thread t1=new Thread(my,"窗口一");

       Thread t2=new Thread(my,"窗口二");

       Thread t3=new Thread(my,"窗口三");

      

       //]启动多线程

       t1.start();

       t2.start();

       t3.start();

    }

}

class myThread implements Runnable{

    private static int tickles=100;

 

    public void run() {

       while(true){

           try {

              Thread.sleep(100);

           } catch (InterruptedException e) {

              System.out.println("该方法是将给系统加入1秒的睡眠时间");

//            e.printStackTrace();

           }

           System.out.println(Thread.currentThread().getName() + "正在出售" + tickles-- + "张票");

       }

      

    }

}


3.  优化改进:需要在多条语句对共享数据操作上进行改进:使用同步代码块将多条语句对共享数据的操作包起来;例: synchronized(同步锁对象){ 多条语句对共享数据操作代码}

4.     同步锁对象:应该每一个线程都要使用这个锁对象(同步锁);该对象可以是任意类的对象

#使用同步代码块改进后的电影院发票程序:

package ThreadText_02;

/**

 * 使用同步锁对象优化改进电影院售票

 * */

public class ThreadText_03 {

    public static void main(String[] args) {

       SellTickles st=new SellTickles();

      

       Thread t1=new Thread(st,"窗口一");

       Thread t2=new Thread(st,"窗口二");

       Thread t3=new Thread(st,"窗口三");

      

       //启动多线程

       t1.start();

       t2.start();

       t3.start();

    }

}

class SellTickles implements Runnable{

    private int tickles=100;

    Object obj=new Object();//创建同步锁对象

   

    public void run() {

       while(true){

           synchronized(obj){

              if(tickles>0){

                  try {

                     Thread.sleep(100);

                  } catch (InterruptedException e) {

                  System.out.println("该方法是模拟售票系统,每卖出一张票后,让系统睡眠0.1");

//                   e.printStackTrace();

                  }

                  System.out.println(Thread.currentThread().getName() + "正在出售" + (tickles--) + "张票");

              }

           }

       }

      

    }

}


5.     Jdk5以后Java提供了一个更具体的锁对象:Lock

Lock 实现提供了比使用 synchronized 方法和语句可获得的更广泛的锁定操作; Lock是一个接口,所以它在使用的是 ReentrantLock子实现类

成员方法: public void lock()获取锁。

                   publicvoid unlock()试图释放此锁

#使用具体锁对存在安全问题的多线程程序执行:

package ThreadText_02;

 

import java.util.concurrent.locks.Lock;

import java.util.concurrent.locks.ReentrantLock;

 

public class ThreadText_04 {

    public static void main(String[] args) {

       SellTickle st=new SellTickle();

      

       //创建Thread类对象

       Thread t1=new Thread(st,"窗口一");

       Thread t2=new Thread(st,"窗口二");

       Thread t3=new Thread(st,"窗口三");

      

       //启动线程

       t1.start();

       t2.start();

       t3.start();

      

      

    }

}

class SellTickle implements Runnable{

    private int tickles=100;

    //创建所对象

    Lock lock=new ReentrantLock();//创建具体锁对象

    public void run() {

       while(true){

           lock.lock();

           if(tickles>0){

              try {

                  Thread.sleep(100);

               } catch(InterruptedException e) {

                  System.out.println("该方法是模拟系统售出票之后,睡眠0.1");

                  //                e.printStackTrace();

              }

              System.out.println(Thread.currentThread().getName() + "正在出售" + (tickles--) + "张票!");

           }

       }

    }

   

}


6.  使用同步机制可以解决多线程的安全问题,但是自身也会有弊端:

1)  同步---->执行效率低(每一个线程在抢占到CPU的执行权,会去将(门)关闭,别的线程进不来)

2)  容易出现死锁现象: 两个或者两个以上的线程出现了互相等待的情况,就会出现死锁!

#使用多线程来模拟死锁线程:

package ThreadText_02;

/**

 * 需求:使用同步代码模拟线程等待(死锁线程)

 * 1.自定义一个类,该类继承自Thread,在该类中定义一个标记标签flag

 * 再重写Thread类的run()方法

 * 2.自定义一个创建所对象类的类LockDemo,在该类中创建两个同步所对象,分别为lock1lock2

 * 3.在主线程中创建自定义类的对象,分别传入参数truefalse参数,然后启动线程

 * */

public class ThreadText_05 {

    public static void main(String[] args) {

       MyThreadDemo m1=new MyThreadDemo(true);

       MyThreadDemo m2=new MyThreadDemo(false);

      

       //启动多线程

       m1.start();

       m2.start();

    }

}

class MyThreadDemo extends Thread{

    private boolean flag;

   

    public MyThreadDemo(boolean flag) {

       this.flag=flag;

       // TODO Auto-generatedconstructor stub

    }

 

    //重写run()方法,

    public void run(){

       if(flag){

           synchronized(LockDemo.lock1){

              System.out.println("这是同步锁lock1!");

              synchronized(LockDemo.lock2){

                  System.out.println("这是同步锁lock2!");

              }

           }

       }else{

           synchronized(LockDemo.lock2){

              System.out.println("这是同步锁lock2!");

              synchronized(LockDemo.lock1){

                  System.out.println("这是同步锁lock1!");

              }

           }

       }

    }

}

class LockDemo {

     //定义两个同步锁对象

    static LockDemo lock1=new LockDemo();

    static LockDemo lock2=new LockDemo();

}


#使用多线程模拟消费者生产者模式:

package ThreadText_02;

/**

 * 需求:使用多线程模拟生产者消费模式,

 * 1.自定义一个生产者类(SetStudent)该类实现接口Runnable,

 * 再自定义一个消费者类(GetStudent)该类也实现Runnable接口,SetStudent类中定义成员信息,

 * GetStudent类中获取成员信息,同时都要重写run() 方法

 * 2.在主线程中国创建Student类对象,再分别创建SetStudent类和getStudent类的对象,将上述

 * 获取到的学生对象当做参数进行传入

 * 3.再分别创建两个Thread类对象,SetStudent类和getStudent类的对象当做参数进行传入

 * 4.需要注意的是,需要在主线程中创一个公共的Student类对象,防止每个线程创建自己的Student类的对象,这样最后输出的结果为null

 *

 *

 * */

public class ThreadText_06 {

    public static void main(String[] args) {

       Student s=new Student();

      

       //创建SetStudent类对象

       SetStudent st=new SetStudent(s);

       //创建GetStudent类对象

       GetStudent gt=new GetStudent(s);

      

       //创建两个Thread类对象

       Thread t1=new Thread(st);

       Thread t2=new Thread(gt);

      

       t1.start();

       t2.start();

    }

}

 

class Student{

    int age;

    String name;

}

 

class SetStudent implements Runnable{

    private Student s;

   

    public SetStudent(Student s) {

       this.s=s;

    }

 

    public void run(){

       s.age=30;

       s.name="wangqiang";

    }

}

 

class GetStudent implements Runnable{

    private Student s;

    public GetStudent(Student s) {

       this.s=s;

    }

    public void run(){

       System.out.println(s.name + "的年龄为" + s.age);

    }

}


7.  线程组

public ThreadGroup(String name): 构造一个新线程组。新线程组的父线程组是目前正在运行线程的线程组。

#多线程的线程组应用:

package ThreadText_02;

/**

 * 需求:在多线程程序中创建一个线程组

 * */

public class ThreadText_07 {

    public static void main(String[] args) {

      

       method2();

       method1();

      

    }

    private static void method2() {

       //创建自定义类对象

       MyThread4 mt=new MyThread4();

      

       //创建Thread类对象

       Thread t1=new Thread(mt,"线程一");

       Thread t2=new Thread(mt,"线程二");

       //启动线程

       t1.start();

       t2.start();

      

       ThreadGroup gp1 = t1.getThreadGroup();

       ThreadGroup gp2 = t2.getThreadGroup();

      

       System.out.println(gp1.getName() + "----" + gp2.getName());

    }

 

    private static void method1() {

ThreadGroup tg=new ThreadGroup("这是一个线程组:");//创建线程组对象

      

       //创建自定义类对象

       MyThread4 mt=new MyThread4();

      

       //创建Thread类对象

       Thread t1=new Thread(tg,mt,"线程一");

       Thread t2=new Thread(tg,mt,"线程二");

      

       //获取线程子线程所在线程组的名称

       ThreadGroup gp1 = t1.getThreadGroup();

       ThreadGroup gp2 = t2.getThreadGroup();

      

       System.out.println(gp1.getName() + "----" + gp2.getName());

      

    }

}

class MyThread4 implements Runnable{

 

    public void run() {

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

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

       }

    }

}

 

 

六, 多线程程序的实现方式3:(使用Executors类来创建线程池对象,来进行异步提交)

1.  创建自定义类对象,该类实现接口Runnable接口,同时在该类中重写该接口中的run()方法.

2.  在主线程中通过Executors类创建线程池对象,并指明该线程池中有几个子线程,

3.  创建两个自定义类的对象

4.  通过线程池对象调用submit()方法,将上述两个对象参数传入,进行异步提交任务

5.  调用Executors类的shutdown()方法,来关闭线程池对象

(1).好处:节约成本; 很多子线程调用完毕不会立即被回收掉,而是会回到线程池中被多次利用!

(2). JDK5新增了一个Executors工厂类来产生线程池

(3)成员方法: public static ExecutorService newFixedThreadPool(int nThreads) Executors工厂类中的这个方法参数直接指定在当前线程池中有多少个线程

例:ExecutorService es=Executors.newFixedThreadPool();

(4)提交任务:

es.submit();

(5)关闭线程池

es.shutdown()

#多线程中使用线程池提交多项任务:

6.  package ThreadText_02;

7.  importjava.util.concurrent.ExecutorService;

8.  importjava.util.concurrent.Executors;

9.  /**

10. * 需求:多线程中使用线程池提交多项任务,并且关闭线程池

11. * */

12.public class ThreadText_08 {

13. public static void main(String[]args) {

14.    //创建线程池对象

15.    ExecutorServicepool=Executors.newFixedThreadPool(2);//该方法中的参数指明线程池中有几个子线程

16.   

17.    //创建自定义类对象

18.    ExecutorsDemoed1=new ExecutorsDemo();

19.    ExecutorsDemoed2=new ExecutorsDemo();

20.   

21.    //使用线程池提交两个子线程

22.    pool.submit(ed1);

23.    pool.submit(ed2);

24.   

25.    //关闭线程池

26.    pool.shutdown();

27. }

28.}

29.class ExecutorsDemo implements Runnable{

30. public void run(){

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

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

33.    }

34. }

35.}


#使用线程池解决线程求和问题:

package CallableText;

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;

 

/**

 * 需求:使用callable接口中的call()方法对线程进行求和:

 * 1.自定义一个类(MyCallabe)该类实现接口Callable<Intager>并指明其泛型为Integer类型

 * 2.在自定义类中定义一个成员变量number,通过有参构造给其赋值,在该类中重写call()方法,该方法会跑胡异常

 * 3.在主线程中常见线程池对象

 * 4.再通过Executors类调用submit()方法,参数传入自定义类的有参构造,并给number赋值

 * 5.关闭线程池对象

 * */

public class CallableText_01 {

    public static void main(String[] args) throws InterruptedException,ExecutionException {

       //创建线程池对象

       ExecutorService pool=Executors.newFixedThreadPool(2);//该方法中的参数指明线程池中有几个子线程

      

       //调用submit()方法返回Future类的对象

       Future<Integer> f1 = pool.submit(new MyCallable(20) );

       Future<Integer> f2 = pool.submit(new MyCallable(10) );

      

       //通过上述对象,然后调用Future类的get()方法,返回具体的结果

       Integer i1= f1.get();

       Integer i2 = f2.get();

      

       //输出结果

       System.out.println("线程一的值:" + i1);

       System.out.println("线程二的值:" + i2);

      

       //关闭线程池

      

    }

}

class MyCallable implements Callable<Integer>{

    private int number;

   

    public MyCallable(int number) {

      

       this.number = number;

    }

 

    public Integer call() throws Exception {

       int sum=0;

       for(int i=1;i<number;i++){

           sum += i;

       }

       return sum;

    }

}


七,Timer类:

该类的成员方法:

 

#在指定的时间点递归删除指定文件夹下的文件及文件夹:

package TimerText;

 

import java.io.File;

import java.text.ParseException;

import java.text.SimpleDateFormat;

import java.util.Date;

import java.util.Timer;

import java.util.TimerTask;

 

/**

 * 需求:在指定的时间删除我们的指定目录(递归删除e:\\盘下FileDemo_01中的文件和文件夹

 * 1.自定义一个类(DeleteDocuments)该类继承自TimerTask

 * 2.在该类中重写该接口的run()方法,再改方法中调用FIle类的构造方法用来封装数据源

 * 3.再在该方法中定义一个递归删除文件及文件夹的方法delete,在该方法中,参数为上述的File类的对象,

 * 用上述封装好的数据源调用isFiles()方法来封装文件夹中的文件及文件夹返回File类型的数组

 * 4.对该File类型的对象数组进行非空判断,然后遍历该数组中的元素

 * 5.加入if()语句然后调用Fiel类的isDirectory()判断该文件是否是文件夹,如果是,继续递归调用delete()方法

 * 如果不是文件夹,直接调用File类的delete()方法,将该文件删除,并且输出该文件的名称

 * 6.if()判断外面再次调用file类的delete()方法,此时用来删除该盘符下的文件夹

 * 7.同时输出删除的文件夹名称

 * 8.在主线程中定义Timer,再定义一个String类型的日期,通过SimplDateFormate对象,格式化为Date 类型的日期

 * 9.在调用Timer类的schedule(),在指定的时间点执行指定的任务

 * */

public class TimerText_01 {

    public static void main(String[] args) throws ParseException {

       Timer t=new Timer();

      

       String StrDate="2017-12-613:45:00";

       //创建SimpleDateFormat对象

       SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

      

       Date date=sdf.parse(StrDate);

       //调用Timer类的schedule()方法

       t.schedule(new DeleteDocuments(), date);

    }

}

class DeleteDocuments extends TimerTask{

 

    @Override

    public void run() {

       File file=new File("e:\\FileDemo_01");//创建File类对象封装数据源

       //定义递归删除文件的方法

       delete( file);

      

    }

 

    private void delete(File file) {

       //File类的listFiles()方法来封装文件元素4

       File[] listFiles = file.listFiles();//返回File类型的数组

      

       //判断该数组是否为空

       if(listFiles!=null){

           for(File f:listFiles){

              if(f.isDirectory()){

                  delete(f);

              }else{

                  System.out.println(f.getName() + "该文件被删除了" + f.delete());

              }

              //if()语句外调用delete()方法,用来删除文件夹

              System.out.println(f.getName() + "该文件夹被删除了" + f.delete());

           }

       }

      

    }

}


#Timer类的Schudle()方法综合应用:

package TimerText;

import java.util.Timer;

import java.util.TimerTask;

/**

 * 需求:Timer类的Schsdule()方法的综合应用:

 * 1.自定义一个类,该类继承自TimerTask,并且在该类中重写run()方法,在该方法中定义一个输出语句

 * 2,在测试类中创建Timer类对象,

 * 3.用上述的Timer类的对象调用public void schedule(TimerTask task, long delay, long period)参数一指明执行的操作,

 * 参数二指明系统过多久之后执行该任务,参数三指明每隔多久之后重新执行该任务

 * */

public class TimerText_02 {

    public static void main(String[] args) {

       Timer t=new Timer();//创建Timer类的对象

      

       //调用Schsdule()方法

       t.schedule(new MyTask(), 3000, 1500);

    }

}

class MyTask extends TimerTask{

    public void run(){

       System.out.println("bom...大爆炸!");

    }

}


八;多线程中匿名内部类的实现:

package ThreadText;

/**

 * 需求:多线程中匿名内部类的方法

 * 1.继承自Thread类的方法实现多线程的匿名内部类

 * 2.实现接口Runnable接口的方法实现匿名内部类的方法

 * */

public class ThreadText_05 {

    public static void main(String[] args) {

       //方法一:继承自Thread

//     new Thread(){

//         public void run(){

//            for(int i=1;i<10;i++){

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

//            }

//         }

//     }.start();

      

       //方法二,实现接口Runnable

       new Thread(new Runnable(){

 

           public void run() {

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

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

              }

             

           }

          

       }).start();

    }

}


九:IO流版模拟用户注册登录:

测试类:

import java.util.Scanner;

import Impl.UserImpl;

import User.User;

import UserDao.UserDao;

 

/**

 * 该类是测试类:在该类中进行键盘录入,让用户进行选择:登录和注册

 * */

public class UserText {

    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);

           System.out.println("请选择:");

           String Choice=Sc.nextLine();

          

           UserDao ud=new UserImpl();//创建接口的子实现类对象

           switch(Choice){

           case "1":

              System.out.println("请输入用户名:");

              String username=Sc.nextLine();

              System.out.println("请输入密码:");

              String password=Sc.nextLine();

             

              boolean isLogin = ud.IsLogin(username, password);

              if(isLogin){

                  System.out.println("恭喜您,登录成功!");

                  System.exit(0);

              }else{

                  System.out.println("您输入的信息有误,请重新输入!");

              }

              break;

           case "2":

              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.Rigest(u);//将上述的User类的对象数据传入该方法

              System.out.println("恭喜你,注册成功!");

              break;

           case "3":

              System.out.println("欢迎光临,下次再来!!");

              System.exit(0);

          

           }

       }

    }

}

用户类:

package User;

/**

 * 需求:在该类中定义同户名个密码成员变量

 * */

public class User {

    private static String UserName;

    private static String PassWord;

   

   

    public User() {

       super();

       // TODO Auto-generatedconstructor stub

    }

    public static String getUserName() {

       return UserName;

    }

    public void setUserName(String userName) {

       UserName = userName;

    }

    public static String getPassWord() {

       return PassWord;

    }

    public void setPassWord(String passWord) {

       PassWord = passWord;

    }

}

用户接口:

package UserDao;

 

import User.User;

 

/**

 * 在该接口中定义两个抽象方法,模拟用户注册和登录

 * */

public interface UserDao {

    public abstract boolean IsLogin(String UserName,String PassWord);

   

    public abstract void Rigest(User user);

}

接口的子实现类

package Impl;

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;

 

import User.User;

import UserDao.UserDao;

 

 

public class UserImpl implements UserDao {

       //创建FIle类的对象,用来封装数据源

    public static File file=new File("User.txt");

    static{

       try {

           file.createNewFile();

       } catch (IOException e) {

           System.out.println("创建文件失败!");

//         e.printStackTrace();

       }

    }

    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[] dates = line.split("=");

              if(dates[0].endsWith(UserName) &&dates[1].endsWith(PassWord)){

                  flag=true;

              }

           }

       } catch (FileNotFoundException e) {

            System.out.println("没有找到指定的文件!");

//         e.printStackTrace();

       } catch (IOException e) {

           System.out.println("用户登录失败!");

//         e.printStackTrace();

       }finally{

           if(br!=null){

              try {

                  br.close();

              } catch (IOException e) {

                  System.out.println("登录失败!");

//                e.printStackTrace();

              }

           }

       }

       return flag;

    }

 

    public void Rigest(User user) {

       //需要创建字符缓冲输出流来向文件中写数据

       BufferedWriter bw=null;

       try {

            bw=new BufferedWriter(new FileWriter(file,true));

           //调用字符缓冲输出流的writer()方法向文件中写数据,同时指明一种格式

           bw.write(User.getUserName() + "=" + User.getPassWord());

           //刷新该流

           bw.flush();

           //调用该流类的特有方法写入换行符

           bw.newLine();

       } catch (IOException e) {

           System.out.println("向文件中写数据失败!");

//         e.printStackTrace();

       }finally{//在该代码中关闭流资源

           if(bw!=null){

              try {

                  bw.close();

              } catch (IOException e) {

                  // TODO Auto-generatedcatch block

                  e.printStackTrace();

              }

           }

       }

      

    }

}

 

 

猜你喜欢

转载自blog.csdn.net/fath_kevin/article/details/78741074