Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/364.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java-使用FileWriter写入同一文件-引入多线程_Java_Multithreading_Filewriter - Fatal编程技术网

Java-使用FileWriter写入同一文件-引入多线程

Java-使用FileWriter写入同一文件-引入多线程,java,multithreading,filewriter,Java,Multithreading,Filewriter,编辑2: 我完全知道两次投票结果接近的原因:OP中没有多线程。所以我编辑了标题 线程不是在OP中,而是在我的答案中 编辑: 好吧,我放弃编辑我的原创文章,让我这样问: date=lun, 22 ene 2018 18:39:42.052;;User-Name=User_703;;NAS-Identifier=NAS_0;;Acct-Status-Type=Start;;Acct-Input-Octets=0;;Acct-Output-Octets=0;; date=lun, 22 ene 201

编辑2: 我完全知道两次投票结果接近的原因:OP中没有多线程。所以我编辑了标题

线程不是在OP中,而是在我的答案中

编辑:

好吧,我放弃编辑我的原创文章,让我这样问:

date=lun, 22 ene 2018 18:39:42.052;;User-Name=User_703;;NAS-Identifier=NAS_0;;Acct-Status-Type=Start;;Acct-Input-Octets=0;;Acct-Output-Octets=0;;
date=lun, 22 ene 2018 18:39:43.827;;User-Name=User_703;;NAS-Identifier=NAS_0;;Acct-Status-Type=Interim-Update;;Acct-Input-Octets=0;;Acct-Output-Octets=0;;
date=lun, 22 ene 2018 18:39:44.463;;User-Name=User_703;;NAS-Identifier=NAS_0;;Acct-Status-Type=Interim-Update;;Acct-Input-Octets=268;;Acct-Output-Octets=42;;
date=lun, 22 ene 2018 18:39:43.968;;User-Name=User_703;;NAS-Identifier=NAS_0;;Acct-Status-Type=Interim-Update;;Acct-Input-Octets=428;;Acct-Output-Octets=143;;
date=lun, 22 ene 2018 18:39:44.039;;User-Name=User_703;;NAS-Identifier=NAS_0;;Acct-Status-Type=Interim-Update;;Acct-Input-Octets=519;;Acct-Output-Octets=294;;
date=lun, 22 ene 2018 18:39:46.276;;User-Name=User_703;;NAS-Identifier=NAS_0;;Acct-Status-Type=Stop;;Acct-Input-Octets=727;;Acct-Output-Octets=535;;
...
date=lun, 22 ene 2018 18:39:42.052;;User-Name=User_703;;NAS-Identifier=NAS_0;;Acct-Status-Type=Start;;Acct-Input-Octets=0;;Acct-Output-Octets=0;;
date=lun, 22 ene 2018 18:39:43.827;;User-Name=User_703;;NAS-Identifier=NAS_0;;Acct-Status-Type=Interim-Update;;Acct-Input-Octets=0;;Acct-Output-Octets=0;;
date=lun, 22 ene 2018 18:39:44.463;;User-Name=User_703;;NAS-Identifier=NAS_0;;Acct-Status-Type=Interim-Update;;Acct-Input-Octets=268;;Acct-Output-Octets=42;;
date=lun, 22 ene 2018 18:39:43.968;;User-Name=User_703;;NAS-Identifier=NAS_0;;Acct-Status-Type=Interim-Update;;Acct-Input-Octets=428;;Acct-Output-Octets=143;;
date=lun, 22 ene 2018 18:39:44.039;;User-Name=User_703;;NAS-Identifier=NAS_0;;Acct-Status-Type=Interim-Update;;Acct-Input-Octets=519;;Acct-Output-Octets=294;;
date=lun, 22 ene 2018 18:39:46.276;;User-Name=User_703;;NAS-Identifier=NAS_0;;Acct-Status-Type=Interim-Update;;Acct-Input-Octets=727;;Acct-Output-Octets=535;;
date=lun, 22 ene 2018 18:39:46.126;;User-Name=User_703;;NAS-Identifier=NAS_0;;Acct-Status-Type=Interim-Update;;Acct-Input-Octets=810;;Acct-Output-Octets=694;;
date=lun, 22 ene 2018 18:39:43.908;;User-Name=User_703;;NAS-Identifier=NAS_0;;Acct-Status-Type=Interim-Update;;Acct-Input-Octets=888;;Acct-Output-Octets=848;;
date=lun, 22 ene 2018 18:39:41.839;;User-Name=User_703;;NAS-Identifier=NAS_0;;Acct-Status-Type=Interim-Update;;Acct-Input-Octets=1007;;Acct-Output-Octets=1078;;
date=lun, 22 ene 2018 18:39:42.163;;User-Name=User_703;;NAS-Identifier=NAS_0;;Acct-Status-Type=Interim-Update;;Acct-Input-Octets=1127;;Acct-Output-Octets=1323;;
date=lun, 22 ene 2018 18:39:43.395;;User-Name=User_703;;NAS-Identifier=NAS_0;;Acct-Status-Type=Interim-Update;;Acct-Input-Octets=1367;;Acct-Output-Octets=1543;;
date=lun, 22 ene 2018 18:39:44.430;;User-Name=User_703;;NAS-Identifier=NAS_0;;Acct-Status-Type=Interim-Update;;Acct-Input-Octets=1487;;Acct-Output-Octets=1656;;
date=lun, 22 ene 2018 18:39:44.760;;User-Name=User_703;;NAS-Identifier=NAS_0;;Acct-Status-Type=Interim-Update;;Acct-Input-Octets=1529;;Acct-Output-Octets=1688;;
date=lun, 22 ene 2018 18:39:43.329;;User-Name=User_703;;NAS-Identifier=NAS_0;;Acct-Status-Type=Stop;;Acct-Input-Octets=1561;;Acct-Output-Octets=1746;;
该日志模拟器旨在生成用户和设备活动的日志。每行包含多个键和值,由
分隔和格式为
key=value
。键为:
用户名
NAS标识符
账户输入八位字节
账户输出八位字节
日期
账户状态类型

用户名
应该是随机的,就像
用户
<代码>NAS标识符
相似。
Acct输入八位字节
Acct输出八位字节
是整数,从0开始,按升序排列;增加的数额是任意的。
date
也应该增加。
Acct Status Type
开始
临时更新
停止
中的一种,表示用户会话的开始、持续状态和结束。应该有一个
开始
,然后是多个
临时更新
,以及一个
停止
。用户和nas在一个会话期间是相同的

因此,它应该生成如下行:

date=lun, 22 ene 2018 18:39:42.052;;User-Name=User_703;;NAS-Identifier=NAS_0;;Acct-Status-Type=Start;;Acct-Input-Octets=0;;Acct-Output-Octets=0;;
date=lun, 22 ene 2018 18:39:43.827;;User-Name=User_703;;NAS-Identifier=NAS_0;;Acct-Status-Type=Interim-Update;;Acct-Input-Octets=0;;Acct-Output-Octets=0;;
date=lun, 22 ene 2018 18:39:44.463;;User-Name=User_703;;NAS-Identifier=NAS_0;;Acct-Status-Type=Interim-Update;;Acct-Input-Octets=268;;Acct-Output-Octets=42;;
date=lun, 22 ene 2018 18:39:43.968;;User-Name=User_703;;NAS-Identifier=NAS_0;;Acct-Status-Type=Interim-Update;;Acct-Input-Octets=428;;Acct-Output-Octets=143;;
date=lun, 22 ene 2018 18:39:44.039;;User-Name=User_703;;NAS-Identifier=NAS_0;;Acct-Status-Type=Interim-Update;;Acct-Input-Octets=519;;Acct-Output-Octets=294;;
date=lun, 22 ene 2018 18:39:46.276;;User-Name=User_703;;NAS-Identifier=NAS_0;;Acct-Status-Type=Stop;;Acct-Input-Octets=727;;Acct-Output-Octets=535;;
...
date=lun, 22 ene 2018 18:39:42.052;;User-Name=User_703;;NAS-Identifier=NAS_0;;Acct-Status-Type=Start;;Acct-Input-Octets=0;;Acct-Output-Octets=0;;
date=lun, 22 ene 2018 18:39:43.827;;User-Name=User_703;;NAS-Identifier=NAS_0;;Acct-Status-Type=Interim-Update;;Acct-Input-Octets=0;;Acct-Output-Octets=0;;
date=lun, 22 ene 2018 18:39:44.463;;User-Name=User_703;;NAS-Identifier=NAS_0;;Acct-Status-Type=Interim-Update;;Acct-Input-Octets=268;;Acct-Output-Octets=42;;
date=lun, 22 ene 2018 18:39:43.968;;User-Name=User_703;;NAS-Identifier=NAS_0;;Acct-Status-Type=Interim-Update;;Acct-Input-Octets=428;;Acct-Output-Octets=143;;
date=lun, 22 ene 2018 18:39:44.039;;User-Name=User_703;;NAS-Identifier=NAS_0;;Acct-Status-Type=Interim-Update;;Acct-Input-Octets=519;;Acct-Output-Octets=294;;
date=lun, 22 ene 2018 18:39:46.276;;User-Name=User_703;;NAS-Identifier=NAS_0;;Acct-Status-Type=Interim-Update;;Acct-Input-Octets=727;;Acct-Output-Octets=535;;
date=lun, 22 ene 2018 18:39:46.126;;User-Name=User_703;;NAS-Identifier=NAS_0;;Acct-Status-Type=Interim-Update;;Acct-Input-Octets=810;;Acct-Output-Octets=694;;
date=lun, 22 ene 2018 18:39:43.908;;User-Name=User_703;;NAS-Identifier=NAS_0;;Acct-Status-Type=Interim-Update;;Acct-Input-Octets=888;;Acct-Output-Octets=848;;
date=lun, 22 ene 2018 18:39:41.839;;User-Name=User_703;;NAS-Identifier=NAS_0;;Acct-Status-Type=Interim-Update;;Acct-Input-Octets=1007;;Acct-Output-Octets=1078;;
date=lun, 22 ene 2018 18:39:42.163;;User-Name=User_703;;NAS-Identifier=NAS_0;;Acct-Status-Type=Interim-Update;;Acct-Input-Octets=1127;;Acct-Output-Octets=1323;;
date=lun, 22 ene 2018 18:39:43.395;;User-Name=User_703;;NAS-Identifier=NAS_0;;Acct-Status-Type=Interim-Update;;Acct-Input-Octets=1367;;Acct-Output-Octets=1543;;
date=lun, 22 ene 2018 18:39:44.430;;User-Name=User_703;;NAS-Identifier=NAS_0;;Acct-Status-Type=Interim-Update;;Acct-Input-Octets=1487;;Acct-Output-Octets=1656;;
date=lun, 22 ene 2018 18:39:44.760;;User-Name=User_703;;NAS-Identifier=NAS_0;;Acct-Status-Type=Interim-Update;;Acct-Input-Octets=1529;;Acct-Output-Octets=1688;;
date=lun, 22 ene 2018 18:39:43.329;;User-Name=User_703;;NAS-Identifier=NAS_0;;Acct-Status-Type=Stop;;Acct-Input-Octets=1561;;Acct-Output-Octets=1746;;
但是,我们可以在这里看到,同一个用户的行都被收集起来了,这不是很真实。我想要的是:

User A Start
User B Start
User C Start
User A Interim-Update
User B Stop
User D Start
User C Interim-Update
User A Interim-Update
...
我想创建几个线程,比如说4个线程,以相互竞争;一个人抓住文件,写一行,然后释放它。然后,另一个线程再次写入文件,一行并退出


OP

我有一个简单的Java类来生成Radius日志的模拟:

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.IntStream;

public class RadiusGenerator {
    private static final String LOG_PATH = "radius-simulation.log";
    private static FileWriter writer;
    private static volatile Map<String, String> user_nas; //ensure the newest value read from main heap; use volatile because we read but not write.
    private static final SimpleDateFormat fmt_in = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss.SSS");
    /* keys in db*/
//    private static final String KEY_TIMESTAMP_HOUR = "timestamp_hour";
//    private static final String KEY_USERID = "user_id";
//    private static final String KEY_NASID = "nas_id";
//    private static final String KEY_TYPE = "type";
//    private static final String KEY_BALANCES = "balances";
//    private static final String KEY_INPUT = "input";
//    private static final String KEY_OUTPUT = "output";

    /* fields in tuple */
    private static final String FIELD_DATE = "date";
    private static final String FIELD_USERNAME = "User-Name";
    private static final String FIELD_NAS_IDENTIFIER = "NAS-Identifier";
    private static final String FIELD_METHOD = "Acct-Status-Type";
    private static final String FIELD_BALANCE_INPUT = "Acct-Input-Octets";
    private static final String FIELD_BALANCE_OUTPUT = "Acct-Output-Octets";

    /* methods */
    private static final String METHOD_START = "Start";
    private static final String METHOD_UPDATE = "Interim-Update";
    private static final String METHOD_STOP = "Stop";
    private static String name;
    private static String nas;
    private static String method;
    private static String result;
    private static int input;
    private static int output;
    private static Date now;


    public static void main(String[] args) {
        // TODO Auto-generated method stub
        try {
            RadiusGenerator.writer = new FileWriter(new File(LOG_PATH), false);
            System.out.println("Initializing with parameters: number of users: " + args[0] + ", number of NAS: " + args[1]);
            int numUsers = Integer.parseInt(args[0]);
            int numNAS = Integer.parseInt(args[1]);
//            List<String> usernames = new ArrayList<String>();
//            IntStream.range(1, numUsers).forEach(i -> {
//                usernames.add("User_" + i);
//            });
//            List<String> nasNames = new ArrayList<String>();
//            IntStream.range(1, numNAS).forEach(i -> {
//                nasNames.add("NAS_" + i);
//            });


            FileWriter writer = new FileWriter(new File(LOG_PATH));
            try {
                for (int i=0; i < generateRandom(20); i++) {
                    int indexUser = generateRandom(numUsers-1);
                    name = "User_" + String.valueOf(indexUser);
                    int indexNas = generateRandom(numNAS-1);
                    nas = "NAS_" + String.valueOf(indexNas);
                    user_nas = new HashMap<String, String>();
                    method = "";
                    result = "";
                    now = new Date();
                    input = 0;
                    output = 0;

                    //first line
                    method = METHOD_START;
                    user_nas.put(name, nas);
                    formLine();
                    //update
                    method = METHOD_UPDATE;
                    do {
                        if (generateRandom(10) == 9) {
                            method = "Stop";
                        }
                        formLine();
                        input += generateRandom(300);
                        output += generateRandom(250);
                    } while (!method.equals(METHOD_STOP));
                    //stop
                    user_nas.remove(name);
                    input = 0;
                    output = 0;
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            writer.write(result);
            writer.flush();
            writer.close();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            System.out.println("The paths is not correct. ");
            e.printStackTrace();
        } catch (NumberFormatException e1) {
            System.out.println("The parameters coming in have wrong formats. Double-check them!");
            e1.printStackTrace();
        }
    }


    private static String concat(String a, String b) {
        return a + "=" + b + ";;";
    }

    private static int generateRandom(int range) {
        return (int) (Math.random() * range);
    }

    private static void formLine() throws IOException {
        result += concat(FIELD_DATE, fmt_in.format(new Date(now.getTime() + (long)generateRandom(5000)))); //randomly add 0-5 seconds
        result += concat(FIELD_USERNAME, name);
        result += concat(FIELD_NAS_IDENTIFIER, nas);
        result += concat(FIELD_METHOD, method);
        result += concat(FIELD_BALANCE_INPUT, String.valueOf(input));
        result += concat(FIELD_BALANCE_OUTPUT, String.valueOf(output));
        result += System.lineSeparator();
    }
}
我们注意到时间戳的顺序不正确;我认为这是因为多个线程同时写入这个文件。我们想要的是,这些行严格按照时间戳排序(在写入时),但是每个用户的
开始
应该先到,然后
更新
,最后
停止
,就像真正的日志一样


Java中的同步问题一直是个难题。如果有人擅长于此,请帮助指出此处应锁定的块或对象。如果有一些好的参考资料,更好;与此同时,我将在家里再次研究此问题。

感谢所有评论,由于您的帮助,我在代码中发现了一些问题,并已修复。线程不在OP中,但在这个答案中我有它

从结果来看,我认为:

  • 访问同一文件时,写入行是原子的:一旦某个线程捕获了该文件,其他线程在所有者完成其行的写入之前无法进行干预,因为写入的行都不是由两个线程的内容组成的
  • 当一个线程完成该行时,它将释放该文件,其他等待的线程可以立即获取该文件并写入他的行。这是一场竞赛,但没有条件竞赛,结果是不一致
所以我想
FileWriter
是线程安全的吗

最终工作代码如下所示:

  • 创建多个
    Runnable
    以写入同一文件
  • 每个
    Runnable
    打开文件并写入一行,立即执行
    flush()
    ,而不执行
    close()
    。要写入的日期是当前时间。在每次写入之间,我通过
    Thread.sleep(xxx)
    添加一些间隔
现在我使用4个启动参数:

100
10
30
D:\temp\radius-simulator.log
课程现在变成:

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ThreadLocalRandom;

/**
 * A generator simulative of Radius log. Generate lines of log and save to a file. 
 * The parameters expected, in order, are: 
 *  - Number of users, integer(will be number of threads running simultaneously)
 *  - Number of NAS, integer
 *  - Number of seconds to sleep between the previous Stop and the next Start of each thread, integer
 *  - The full path of log file, string (the app in Windows has right to create file, but not the parent folder,
 *      so be sure to create the parent folder first)
 *  
 *
 */
public class RadiusSimulator implements Runnable {
    private static File log;
    private static volatile Map<String, String> user_nas; //ensure the newest value read from main heap; use volatile because we read but not write.
    private static final SimpleDateFormat fmt_in = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss.SSS");

    /* fields in tuple */
    private static final String FIELD_DATE = "date";
    private static final String FIELD_USERNAME = "User-Name";
    private static final String FIELD_NAS_IDENTIFIER = "NAS-Identifier";
    private static final String FIELD_METHOD = "Acct-Status-Type";
    private static final String FIELD_BALANCE_INPUT = "Acct-Input-Octets";
    private static final String FIELD_BALANCE_OUTPUT = "Acct-Output-Octets";

    /* methods */
    private static final String METHOD_START = "Start";
    private static final String METHOD_UPDATE = "Interim-Update";
    private static final String METHOD_STOP = "Stop";

    /* parameters */
    private static int numUsers;
    private static int numNAS;
    private static int sleepTime;

    private String username;
    private String nas;
    private String method;
    private String result;
    private int input;
    private int output;

    private FileWriter writer;
    private int status;
    private boolean stop;
    private String name;


    public RadiusSimulator(String name) {
        this.name = name;
        this.method = METHOD_START;
        status = 0;
        stop = false;
        // just open the file without appending, to clear content
        try {
            writer = new FileWriter(log, false);
            writer.close();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }


    public static void main(String[] args) {
        try {
            System.out.println("/**\r\n" + 
                    " * A simulated generator of Radius log. Generate lines of log and save to a file. \r\n" + 
                    " * The parameters expected, in order, are: \r\n" + 
                    " *  - Number of users, integer(will be number of threads running simultaneously)\r\n" + 
                    " *  - Number of NAS, integer\r\n" + 
                    " *  - Number of maximum of seconds to sleep between the previous Stop and the next Start of each thread, integer(>60)\r\n" + 
                    " *  - The full path of log file, string (be sure to create the parent folder first)\r\n" + 
                    " *  \r\n" + 
                    " * (require Java 1.7 or above) \r\n\"" +
                    " *  \r\n" + 
                    " *\r\n" + 
                    " */");

            System.out.println("Initializing with parameters: number of users: " + args[0] + ", number of NAS: " + args[1]);
            numUsers = Integer.parseInt(args[0]);
            numNAS = Integer.parseInt(args[1]);
            sleepTime = Integer.parseInt(args[2]);
            log = new File(args[3]);
            for (int i=0; i<numUsers; i++) {
                new Thread(new RadiusSimulator("User_" + i)).start();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }



    }

    private int generateRandom(int min, int max) {
        if (max < min) max = min;
        int randomNum = ThreadLocalRandom.current().nextInt(min, max + 1);
        return randomNum;
    }

    private static String concat(String a, String b) {
        return a + "=" + b + ";;";
    }

    private void formLine() throws IOException {
        result += concat(FIELD_DATE, fmt_in.format(new Date())); //print always the date of now
        result += concat(FIELD_USERNAME, name);
        result += concat(FIELD_NAS_IDENTIFIER, nas);
        result += concat(FIELD_METHOD, method);
        result += concat(FIELD_BALANCE_INPUT, String.valueOf(input));
        result += concat(FIELD_BALANCE_OUTPUT, String.valueOf(output));
        result += System.lineSeparator();
    }
    @Override
    public void run() {
        try {
            writer = new FileWriter(log, true);
        } catch (IOException e1) {
            e1.printStackTrace();
        }
//        while (!stop) {
        while (true) {
            try {
                Thread.sleep(generateRandom(0, 3000));
                if (status == 0) {
                    // stage 1
                    int indexUser = generateRandom(0, numUsers-1);
                    username = "User_" + String.valueOf(indexUser);
                    int indexNas = generateRandom(0, numNAS-1);
                    nas = "NAS_" + String.valueOf(indexNas);
                    user_nas = new HashMap<String, String>();
                    result = "";
                    input = 0;
                    output = 0;
                    //first line
                    user_nas.put(username, nas);
                    formLine();
                    System.out.println(result);
                    writer.write(result);
                    writer.flush();
                    status ++; //next stage
                    result = "";
                } else if (status == 1) {
                    method = METHOD_UPDATE;
                    input += generateRandom(0, 400);
                    output += generateRandom(0, 500);
                    formLine();
                    System.out.println(result);
                    writer.write(result);
                    writer.flush();
                    // 1 out of 10 of probability to enter stage 3
                    if (generateRandom(0, 10) == 9) {
                        status = 2;
                    }
                    result = "";
                } else if (status == 2) {
                    method = METHOD_STOP;
                    input += generateRandom(0, 400);
                    output += generateRandom(0, 500);
                    formLine();
                    System.out.println(result);
                    /* write inmediately after constructing the line */
                    writer.write(result);
                    writer.flush();
                    user_nas.remove(username);
                    input = 0;
                    output = 0;
//                    stop = true;
                    result = "";
                    status = 0; //go back to stage 1
                    Thread.sleep(generateRandom(60*1000, sleepTime*1000));
                }
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}
导入java.io.File;
导入java.io.FileWriter;
导入java.io.IOException;
导入java.text.simpleDataFormat;
导入java.util.Date;
导入java.util.HashMap;
导入java.util.Map;
导入java.util.concurrent.ThreadLocalRandom;
/**
*模拟半径测井曲线的发生器。生成日志行并保存到文件。
*预期参数依次为:
*-用户数,整数(将是同时运行的线程数)
*-NAS的数量,整数
*-每个线程上一次停止和下一次开始之间的睡眠秒数,整数
*-日志文件的完整路径,字符串(Windows中的应用程序有权创建文件,但无权创建父文件夹,
*因此,请确保先创建父文件夹)
*  
*
*/
公共类RadiusSimulator实现Runnable{
私有静态文件日志;
private static volatile Map user_nas;//确保从主堆读取最新值;使用volatile,因为我们读取但不写入。
私有静态最终简化格式fmt_in=新简化格式(“EEE,dd MMM yyyy HH:mm:ss.SSS”);
/*元组中的字段*/
私有静态最终字符串字段\u DATE=“DATE”;
私有静态最终字符串字段\u USERNAME=“User Name”;
专用静态最终字符串字段\u NAS\u IDENTIFIER=“NAS IDENTIFIER”;
私有静态最终字符串字段\u METHOD=“账户状态类型”;
私有静态最终字符串字段\u BALANCE\u INPUT=“Acct INPUT Octets”;
私有静态最终字符串字段\u BALANCE\u OUTPUT=“Acct OUTPUT Octets”;
/*方法*/
私有静态最终字符串方法\u START=“START”;
私有静态最终字符串方法\u UPDATE=“临时更新”;
私有静态最终字符串方法\u STOP=“STOP”;
/*参数*/
私人静态干扰;
私有静态整数;
私人睡眠时间;
私有字符串用户名;
私有字符串nas;
私有字符串方法;
私有字符串结果;
私有int输入;
私有整数输出;
私有文件编写器;
私人身份;
私有布尔停止;
私有字符串名称;
公共放射刺激器(字符串名称){
this.name=名称;
this.method=method\u START;
状态=0;
停止=错误;
//只需打开文件而不追加,即可清除cont