A. java多线程怎么测试
测试并发的性能吗?可以用Jmeter进行模拟多线程测试
B. java多线程有几种实现方法,都是什么同步有几种实现方法,都是什么
java中多线程的实现方法有两种:1.直接继承thread类;2.实现runnable接口;同步的实现方法有五种:1.同步方法;2.同步代码块;3.使用特殊域变量(volatile)实现线程同步;4.使用重入锁实现线程同步;5.使用局部变量实现线程同步
。
其中多线程实现过程中需注意重写或者覆盖run()方法,而对于同步的实现方法中使用较常使用的是利用synchronized编写同步方法和代码块。
C. java如何模拟一个多线程环境
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
public class FrameTest extends JFrame {
public FrameTest() {
super("Swing 例子");
this.setSize(300, 200);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setLayout(new FlowLayout());
this.add(new CounterJButton());
this.add(new CounterJButton());
this.add(new CounterJButton());
this.setVisible(true);
}
static class CounterJButton extends JButton implements Runnable,
ActionListener {
private boolean started = false;
private int count = 0;
public CounterJButton() {
super("按我开始计数");
this.addActionListener(this);
}
public void run() {
while (started) {
this.setText("按我暂停 " + String.valueOf(count++));
try {
Thread.sleep(100);
} catch (InterruptedException e) {
}
}
}
public void actionPerformed(ActionEvent e) {
if (started) {
this.started = false;
this.setText("按我恢复计数 " + count);
} else {
this.started = true;
new Thread(this).start();
}
}
}
public static void main(String[] args) {
new FrameTest();
}
}
D. 什么是Java多线程编程
一、 什么是多线程:
我们现在所使用操作系统都是多任务操作系统(早期使用的DOS操作系统为单任务操作系统),多任务操作指在同一时刻可以同时做多件事(可以同时执行多个程序)。
多进程:每个程序都是一个进程,在操作系统中可以同时执行多个程序,多进程的目的是为了有效的使用CPU资源,每开一个进程系统要为该进程分配相关的系统资源(内存资源)
多线程:线程是进程内部比进程更小的执行单元(执行流|程序片段),每个线程完成一个任务,每个进程内部包含了多个线程每个线程做自己的事情,在进程中的所有线程共享该进程的资源;
主线程:在进程中至少存在一个主线程,其他子线程都由主线程开启,主线程不一定在其他线程结束后结束,有可能在其他线程结束前结束。Java中的主线程是main线程,是Java的main函数;
二、 Java中实现多线程的方式:
继承Thread类来实现多线程:
当我们自定义的类继承Thread类后,该类就为一个线程类,该类为一个独立的执行单元,线程代码必须编写在run()方法中,run方法是由Thread类定义,我们自己写的线程类必须重写run方法。
run方法中定义的代码为线程代码,但run方法不能直接调用,如果直接调用并没有开启新的线程而是将run方法交给调用的线程执行
要开启新的线程需要调用Thread类的start()方法,该方法自动开启一个新的线程并自动执行run方法中的内容
java多线程的启动顺序不一定是线程执行的顺序,各个线程之间是抢占CPU资源执行的,所有有可能出现与启动顺序不一致的情况。
CPU的调用策略:
如何使用CPU资源是由操作系统来决定的,但操作系统只能决定CPU的使用策略不能控制实际获得CPU执行权的程序。
线程执行有两种方式:
1.抢占式:
目前PC机中使用最多的一种方式,线程抢占CPU的执行权,当一个线程抢到CPU的资源后并不是一直执行到此线程执行结束,而是执行一个时间片后让出CPU资源,此时同其他线程再次抢占CPU资源获得执行权。
2.轮循式;
每个线程执行固定的时间片后让出CPU资源,以此循环执行每个线程执行相同的时间片后让出CPU资源交给下一个线程执行。
希望对您有所帮助!~
E. 用java编写多线程银行ATM 模拟程序
先构建一个客户端,再构建一个服务器端,其实做一个简单的界面,建立一个数据库,调用SQl 语句,,实现单机,模拟多线程的就可以了,服务器部分不做也可以模拟出来。。
PS:这不会是程序专题训练一吧。。。
F. JAVA多线程 模拟每隔一秒输入一个数据
在编写Java程序时,有时候需要在Java程序中执行另外一个程序。
1、启动程序Java提供了两种方法用来启动其它程序:
(1)使用Runtime的exec()方法
(2)使用ProcessBuilder的start()方法
不管在哪种操作系统下,程序具有基本类似的一些属性。一个程序启动后就程序操作系统的一个进程,进程在执行的时候有自己的环境变量、有自己的工作目录。Runtime和ProcessBuilder提供了不同的方式来启动程序,设置启动参数、环境变量和工作目录。
能够在Java中执行的外部程序,必须是一个实际存在的可执行文件,对于shell下的内嵌命令是不能直接执行的。
采用Runtime的exec执行程序时,首先要使用Runtime的静态方法得到一个Runtime,然后调用Runtime的exec方
法。可以将要执行的外部程序和启动参数、环境变量、工作目录作为参数传递给exec方法,该方法执行后返回一个Process代表所执行的程序。
Runtime有六个exec方法,其中两个的定义为:
public Process exec(String[] cmdarray, String[] envp, File dir)
public Process exec(String command, String[] envp, File dir)
cmdarray和command为要执行的命令,可以将命令和参数作为一个字符串command传递给exec()方法,也可以将命令和参数一个一个的方在数组cmdarray里传递给exec()方法。
envp为环境变量,以name=value的形式放在数组中。dir为工作目录。
可以不要dir参数,或者不要envp和dir参数,这样就多出了其它4个exec()方法。如果没有dir参数或者为null,那么新启动的
进程就继承当前java进程的工作目录。如果没有envp参数或者为null,那么新启动的进程就继承当前java进程的环境变量。
也可以使用ProcessBuilder类启动一个新的程序,该类是后来添加到JDK中的,而且被推荐使用。通过构造函数设置要执行的命令以及
参数,或者也可以通过command()方法获取命令信息后在进行设置。通过directory(File directory)
方法设置工作目录,通过environment()获取环境变量信息来修改环境变量。
在使用ProcessBuilder构造函数创建一个新实例,设置环境变量、工作目录后,可以通过start()方法来启动新程序,与Runtime的exec()方法一样,该方法返回一个Process对象代表启动的程序。
ProcessBuilder与Runtime.exec()方法的不同在于ProcessBuilder提供了
redirectErrorStream(boolean redirectErrorStream)
方法,该方法用来将进程的错误输出重定向到标准输出里。即可以将错误输出都将与标准输出合并。
2、Process
不管通过那种方法启动进程后,都会返回一个Process类的实例代表启动的进程,该实例可用来控制进程并获得相关信息。Process 类提供了执行从进程输入、执行输出到进程、等待进程完成、检查进程的退出状态以及销毁(杀掉)进程的方法:
(1) void destroy()
杀掉子进程。
一般情况下,该方法并不能杀掉已经启动的进程,不用为好。
(2) int exitValue()
返回子进程的出口值。
只有启动的进程执行完成、或者由于异常退出后,exitValue()方法才会有正常的返回值,否则抛出异常。
(3)InputStream getErrorStream()
获取子进程的错误流。
如果错误输出被重定向,则不能从该流中读取错误输出。
(4)InputStream getInputStream()
获取子进程的输入流。
可以从该流中读取进程的标准输出。
(5)OutputStream getOutputStream()
获取子进程的输出流。
写入到该流中的数据作为进程的标准输入。
(6) int waitFor()
导致当前线程等待,如有必要,一直要等到由该 Process 对象表示的进程已经终止。
通过该类提供的方法,可以实现与启动的进程之间通信,达到交互的目的。
3、从标准输出和错误输出流读取信息
从启动其他程序的Java进程看,已启动的其他程序输出就是一个普通的输入流,可以通过getInputStream()和getErrorStream来获取。
对于一般输出文本的进程来说,可以将InputStream封装成BufferedReader,然后就可以一行一行的对进程的标准输出进行处理。
4、举例
(1)Runtime.exec()
import java.io.BufferedReader;
import java.io.File;
import java.io.InputStreamReader;
public class Test1 {
public static void main(String[] args) {
try {
Process p = null;
String line = null;
BufferedReader stdout = null;
//list the files and directorys under C:\
p = Runtime.getRuntime().exec("CMD.exe /C dir", null, new File("C:\\"));
stdout = new BufferedReader(new InputStreamReader(p
.getInputStream()));
while ((line = stdout.readLine()) != null) {
System.out.println(line);
}
stdout.close();
//echo the value of NAME
p = Runtime.getRuntime().exec("CMD.exe /C echo %NAME%", new String[] {"NAME=TEST"});
stdout = new BufferedReader(new InputStreamReader(p
.getInputStream()));
while ((line = stdout.readLine()) != null) {
System.out.println(line);
}
stdout.close();
} catch (Exception e) {
e.printStackTrace();
}
}
(2)ProcessBuilder
import java.io.BufferedReader;
import java.io.File;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
public class Test2 {
public static void main(String[] args) {
try {
List list = new ArrayList();
ProcessBuilder pb = null;
Process p = null;
String line = null;
BufferedReader stdout = null;
//list the files and directorys under C:\
list.add("CMD.EXE");
list.add("/C");
list.add("dir");
pb = new ProcessBuilder(list);
pb.directory(new File("C:\\"));
p = pb.start();
stdout = new BufferedReader(new InputStreamReader(p
.getInputStream()));
while ((line = stdout.readLine()) != null) {
System.out.println(line);
}
stdout.close();
//echo the value of NAME
pb = new ProcessBuilder();
mand(new String[] {"CMD.exe", "/C", "echo %NAME%"});
pb.environment().put("NAME", "TEST");
p = pb.start();
stdout = new BufferedReader(new InputStreamReader(p
.getInputStream()));
while ((line = stdout.readLine()) != null) {
System.out.println(line);
}
stdout.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
5、获取进程的返回值
通常,一个程序/进程在执行结束后会向操作系统返回一个整数值,0一般代表执行成功,非0表示执行出现问题。有两种方式可以用来获取进程的返回
值。一是利用waitFor(),该方法是阻塞的,执导进程执行完成后再返回。该方法返回一个代表进程返回值的整数值。另一个方法是调用
exitValue()方法,该方法是非阻塞的,调用立即返回。但是如果进程没有执行完成,则抛出异常。
6、阻塞的问题
由Process代表的进程在某些平台上有时候并不能很好的工作,特别是在对代表进程的标准输入流、输出流和错误输出进行操作时,如果使用不慎,有可能导致进程阻塞,甚至死锁。
如果将以上事例中的从标准输出重读取信息的语句修改为从错误输出流中读取:
stdout = new BufferedReader(new InputStreamReader(p
.getErrorStream()));
那么程序将发生阻塞,不能执行完成,而是hang在那里。
当进程启动后,就会打开标准输出流和错误输出流准备输出,当进程结束时,就会关闭他们。在以上例子中,错误输出流没有数据要输出,标准输出流中
有数据输出。由于标准输出流中的数据没有被读取,进程就不会结束,错误输出流也就不会被关闭,因此在调用readLine()方法时,整个程序就会被阻
塞。为了解决这个问题,可以根据输出的实际先后,先读取标准输出流,然后读取错误输出流。
但是,很多时候不能很明确的知道输出的先后,特别是要操作标准输入的时候,情况就会更为复杂。这时候可以采用线程来对标准输出、错误输出和标准输入进行分别处理,根据他们之间在业务逻辑上的关系决定读取那个流或者写入数据。
针对标准输出流和错误输出流所造成的问题,可以使用ProcessBuilder的redirectErrorStream()方法将他们合二为一,这时候只要读取标准输出的数据就可以了。
当在程序中使用Process的waitFor()方法时,特别是在读取之前调用waitFor()方法时,也有可能造成阻塞。可以用线程的方法来解决这个问题,也可以在读取数据后,调用waitFor()方法等待程序结束。
总之,解决阻塞的方法应该有两种:
(1)使用ProcessBuilder类,利用redirectErrorStream方法将标准输出流和错误输出流合二为一,在用start()方法启动进程后,先从标准输出中读取数据,然后调用waitFor()方法等待进程结束。
如:
import java.io.BufferedReader;
import java.io.File;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
public class Test3 {
public static void main(String[] args) {
try {
List list = new ArrayList();
ProcessBuilder pb = null;
Process p = null;
String line = null;
BufferedReader stdout = null;
//list the files and directorys under C:\
list.add("CMD.EXE");
list.add("/C");
list.add("dir");
pb = new ProcessBuilder(list);
pb.directory(new File("C:\\"));
//merge the error output with the standard output
pb.redirectErrorStream(true);
p = pb.start();
//read the standard output
stdout = new BufferedReader(new InputStreamReader(p
.getInputStream()));
while ((line = stdout.readLine()) != null) {
System.out.println(line);
}
int ret = p.waitFor();
System.out.println("the return code is " + ret);
stdout.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
(2)使用线程
import java.util.*;
import java.io.*;
class StreamWatch extends Thread {
InputStream is;
String type;
List output = new ArrayList();
boolean debug = false;
StreamWatch(InputStream is, String type) {
this(is, type, false);
}
StreamWatch(InputStream is, String type, boolean debug) {
this.is = is;
this.type = type;
this.debug = debug;
}
public void run() {
try {
PrintWriter pw = null;
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String line = null;
while ((line = br.readLine()) != null) {
output.add(line);
if (debug)
System.out.println(type + ">" + line);
}
if (pw != null)
pw.flush();
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
public List getOutput() {
return output;
}
}
public class Test5 {
public static void main(String args[]) {
try {
List list = new ArrayList();
ProcessBuilder pb = null;
Process p = null;
// list the files and directorys under C:\
list.add("CMD.EXE");
list.add("/C");
list.add("dir");
pb = new ProcessBuilder(list);
pb.directory(new File("C:\\"));
p = pb.start();
// process error and output message
StreamWatch errorWatch = new StreamWatch(p.getErrorStream(),
"ERROR");
StreamWatch outputWatch = new StreamWatch(p.getInputStream(),
"OUTPUT");
// start to watch
errorWatch.start();
outputWatch.start();
//wait for exit
int exitVal = p.waitFor();
//print the content from ERROR and OUTPUT
System.out.println("ERROR: " + errorWatch.getOutput());
System.out.println("OUTPUT: " + outputWatch.getOutput());
System.out.println("the return code is " + exitVal);
} catch (Throwable t) {
t.printStackTrace();
}
}
}
7、在Java中执行Java程序
执行一个Java程序的关键在于:
(1)知道JAVA虚拟机的位置,即java.exe或者java的路径
(2)知道要执行的java程序的位置
(3)知道该程序所依赖的其他类的位置
举一个例子,一目了然。
(1)待执行的Java类
public class MyTest {
public static void main(String[] args) {
System.out.println("OUTPUT one");
System.out.println("OUTPUT two");
System.err.println("ERROR 1");
System.err.println("ERROR 2");
for(int i = 0; i < args.length; i++)
{
System.out.printf("args[%d] = %s.", i, args[i]);
}
}
}
(2)执行该类的程序
import java.util.*;
import java.io.*;
class StreamWatch extends Thread {
InputStream is;
String type;
List output = new ArrayList();
boolean debug = false;
StreamWatch(InputStream is, String type) {
this(is, type, false);
}
StreamWatch(InputStream is, String type, boolean debug) {
this.is = is;
this.type = type;
this.debug = debug;
}
public void run() {
try {
PrintWriter pw = null;
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String line = null;
while ((line = br.readLine()) != null) {
output.add(line);
if (debug)
System.out.println(type + ">" + line);
}
if (pw != null)
pw.flush();
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
public List getOutput() {
return output;
}
}
public class Test6 {
public static void main(String args[]) {
try {
List list = new ArrayList();
ProcessBuilder pb = null;
Process p = null;
String java = System.getProperty("java.home") + File.separator + "bin" + File.separator + "java";
String classpath = System.getProperty("java.class.path");
// list the files and directorys under C:\
list.add(java);
list.add("-classpath");
list.add(classpath);
list.add(MyTest.class.getName());
list.add("hello");
list.add("world");
list.add("good better best");
pb = new ProcessBuilder(list);
p = pb.start();
System.out.println(mand());
// process error and output message
StreamWatch errorWatch = new StreamWatch(p.getErrorStream(),
"ERROR");
StreamWatch outputWatch = new StreamWatch(p.getInputStream(),
"OUTPUT");
// start to watch
errorWatch.start();
outputWatch.start();
//wait for exit
int exitVal = p.waitFor();
//print the content from ERROR and OUTPUT
System.out.println("ERROR: " + errorWatch.getOutput());
System.out.println("OUTPUT: " + outputWatch.getOutput());
System.out.println("the return code is " + exitVal);
} catch (Throwable t) {
t.printStackTrace();
}
}
}
G. java模拟龟兔赛跑问题用多线程实现
import java.util.Date;
public class Test extends Thread{ private int tortoise_walk = 0; // 乌龟已跑长度存放变量
private int rabbit_walk = 0; // 兔子已跑长度存放变量
private int finish = 1000; // 终点
private volatile boolean hasWinner = false;// 胜利者诞生 /**
*
* @ClassName: Tortoise_Run
* @Description: TODO(乌龟奔跑线程)
* @author guotingchao
* @date 2012-3-6 上午10:20:45
*
*/
class Tortoise_Run implements Runnable {
@Override
public void run() {
try {
while (!hasWinner) {
if (tortoise_walk % 100 == 0 && (tortoise_walk != 0||tortoise_walk>=finish)) { //乌龟每100米休息500毫秒
System.out.println("乌龟休息中………………");
Thread.sleep(500);
}
tortoise_walk++;
System.out.println("乌龟已跑"+tortoise_walk+"米");
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
} /**
*
* @ClassName: Rabbit_Run
* @Description: TODO(兔子奔跑线程)
* @date 2012-3-6 上午10:25:10
* @author guotingchao
*/
class Rabbit_Run implements Runnable {
@Override
public void run() {
try {
while (!hasWinner) {
if (rabbit_walk % 20 == 0 && (rabbit_walk != 0||rabbit_walk>=finish)) { //兔子每20米休息500毫秒
System.out.println("兔子休息中………………");
Thread.sleep(500);
}
rabbit_walk=rabbit_walk+5; //每秒跑5步
System.out.println("兔子已跑"+rabbit_walk+"米");
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
@Override
public void run(){
new Thread(new Rabbit_Run()).start();
new Thread(new Tortoise_Run()).start();
}
/**
* @Title: main
* @Description: TODO(
* 赛程1000米,兔子跑5米,乌龟跑1米,兔子每20米休息500毫秒,乌龟每100米休息500毫秒。谁先到终点就结束程序
* ,并显示获胜方。)
* @param @param args
* @param @throws Exception 设定文件
* @author guotingchao
* @return void 返回类型
* @throws
*/
public static void main(String[] args) throws Exception {
long temp_actionTime=System.currentTimeMillis();
System.out.println("比赛开始:"+new Date(temp_actionTime)+"毫秒");
Test t=new Test();
new Thread(t).start();
while(true){
if(t.tortoise_walk>=t.finish||t.rabbit_walk>=t.finish){
t.hasWinner=true;
break;
}
}
String winnnerName=t.tortoise_walk>t.rabbit_walk?"乌龟":"兔子";
long temp_lastTime=System.currentTimeMillis();
System.out.println(winnnerName+"胜利");
System.out.println("比赛结束:"+new Date(temp_lastTime)+"毫秒");
System.out.println("所耗时间:"+(temp_lastTime-temp_actionTime)+"毫秒");
System.out.println("兔子="+t.rabbit_walk+" 乌龟="+t.tortoise_walk);
}
}
//不知道兔子和乌龟的步长时间是否按每秒。 这里程序只考虑依次递增频率
H. java多线程有几种实现方法
继承Thread类来实现多线程:
当我们自定义的类继承Thread类后,该类就为一个线程类,该类为一个独立的执行单元,线程代码必须编写在run()方法中,run方法是由Thread类定义,我们自己写的线程类必须重写run方法。
run方法中定义的代码为线程代码,但run方法不能直接调用,如果直接调用并没有开启新的线程而是将run方法交给调用的线程执行
要开启新的线程需要调用Thread类的start()方法,该方法自动开启一个新的线程并自动执行run方法中的内容
*java多线程的启动顺序不一定是线程执行的顺序,各个线程之间是抢占CPU资源执行的,所有有可能出现与启动顺序不一致的情况。
CPU的调用策略:
如何使用CPU资源是由操作系统来决定的,但操作系统只能决定CPU的使用策略不能控制实际获得CPU执行权的程序。
线程执行有两种方式:
1.抢占式:
目前PC机中使用最多的一种方式,线程抢占CPU的执行权,当一个线程抢到CPU的资源后并不是一直执行到此线程执行结束,而是执行一个时间片后让出CPU资源,此时同其他线程再次抢占CPU资源获得执行权。
2.轮循式;
每个线程执行固定的时间片后让出CPU资源,以此循环执行每个线程执行相同的时间片后让出CPU资源交给下一个线程执行。
I. java使用多线程模拟这一过程
packageknow;
publicclassT31{
publicstaticintpeaches=100;
(intnum,intmypeach){
inti=peaches/2+peaches%2;
peaches-=i;
mypeach+=i;
System.out.println("第"+num+"只猴子抢到了桃子,这次抢到"+i+"个,现在有:"+mypeach+"个");
returnmypeach;
}
publicstaticvoidmain(String[]args)throwsInterruptedException{
Threadmonkey1=newThread(){
publicvoidrun(){
intmypeach=0;
while(peaches>1){
mypeach=fetch(1,mypeach);
}
}
};
Threadmonkey2=newThread(){
publicvoidrun(){
intmypeach=0;
while(peaches>1){
mypeach=fetch(2,mypeach);
}
}
};
Threadmonkey3=newThread(){
publicvoidrun(){
intmypeach=0;
while(peaches>1){
mypeach=fetch(3,mypeach);
}
}
};
monkey1.start();
monkey2.start();
monkey3.start();
}
}
J. java多线程--模拟接力赛跑
import java.util.*;
public class Main {
public static void main(String[] args) {
RunThread run = new RunThread();
for (int i = 1; i <= 5; ++i) {
new Thread(run, i + "号选手").start();
}
}
}
class RunThread implements Runnable {
int distance;
@Override
public synchronized void run() {
String name = Thread.currentThread().getName();
System.out.println(name + "拿到接力棒!");
for (int i = 0; i < 10; ++i) {
distance += 10;
System.out.println(name + "跑到了" + distance + "米!");
}
}
}