java 多线程中每个线程中new一个对象使用还是有问题,各位大神帮忙看看,什么原理

-//代码如下,启动多个线程,每个线程线程中 new Test1 使用,但是在Test1 的方法中打印大概率中存在重复的输入,请问这是为什么?
package com;

import java.util.ArrayList;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;

public class Test2 {
public static void main(String[] args){
//System.out.println(System.getProperty("java.version"));
//System.out.println(Math.random());
final String xmlhead1="xmlhead1";
final String xmlbody1="xmlbody1";

 final String xmlhead2="xmlhead2";
 final String xmlbody2="xmlbody2";
ExecutorService exec = Executors.newCachedThreadPool(); 
final Semaphore semp = new Semaphore(5); 

for (int index = 0; index < 1000; index++) {
Runnable run = new Runnable() {
public void run() {
try {
// 获取许可
semp.acquire();
if(Math.random()>=(0.5)){
Test1 testone=new Test1();
//synchronized (testone){
testone.parseString(xmlhead1, xmlbody1);
//}
}
else{
Test1 testtwo=new Test1();
//synchronized (testtwo){
testtwo.parseString(xmlhead2, xmlbody2);
//}
}
semp.release();
}catch(Exception e){
e.printStackTrace();
}
}
};
exec.execute(run);
}
exec.shutdown();

}

}
class Test1 {
public String parseString(String head,String body){
System.out.println("parseString:"+this.toString());
return head+body;
}
}

2个回答

内存地址的分配与垃圾回收的,

dingshanwei123
dingshanwei123 回复sundianzhe: 也遇到类似的问题,new的对象,多线程进去打印有时有重复的,偶发的,不知道具体什么原因
5 个月之前 回复
sundianzhe
sundianzhe 回复丵鹰: 如代码中所示的,我在代码中加了同步锁,就不会发生这个问题,这有事为什么?
接近 3 年之前 回复
strutce
丵鹰 回复sundianzhe: 内存地址相同是jvm自行判断使用回收的
接近 3 年之前 回复
sundianzhe
sundianzhe 回复丵鹰: 那这样不会有问题吗?实际开发中遇到的问题就是,new一个类来解析报文,但是发现同一时间进来两条访问,而其中一条实行了两次,而另一条却没有执行
接近 3 年之前 回复
strutce
丵鹰 回复sundianzhe: 是的
接近 3 年之前 回复
sundianzhe
sundianzhe 你是说new的对象分配的地址相同造成的?
接近 3 年之前 回复

不知道我理解你的问题是否正确,你是不是想问为什么打印的结果1,2不是顺序呢来的?而是一会儿1一会儿2或者一堆1再一堆2?
这个是多线程没有进行自主控制,是由操作系统的任务调度执行的,不能改善,可以人为的控制线程;你如果想要顺序的打印出结果,可以
使用synchronized(线程互斥)与wait(),notify()来配合完成顺序打印出结果。
如果你想问的不是这个,请把问题说的再详细点,我可以给你进一步的解答,谢谢!

wal1314520
wal1314520 回复sundianzhe: 如果被分配了相同的地址,就会出现相同的问题,这个是虚拟机决定的,没法控制
接近 3 年之前 回复
sundianzhe
sundianzhe 不是顺序的问题,而是打印的这1000行结果,是有重复的,我的理解是既然new一个对象,打印的结果不应该存在重复的值啊
接近 3 年之前 回复
Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!
其他相关推荐
java多线程读取hbase, 是单例一个client供所有线程使用好呢 ,还是每个线程自己创建线程好呢
java多线程读取hbase, 是单例一个client供所有线程使用好呢 ,还是每个线程自己创建线程好呢 我想明白 ,单例client 与 new 多个client 想比较, 的优缺点和用处
多线程socket编程的问题,使用BIO模式的话,一个线程只能处理一个Socket吗?
我在做一些网络编程相关的学习,写了一个Demo,类似于一个聊天室,有一个WebServer,多个Client,当Client发起连接时,Server创建一个线程来处理,由于Client特别多,我打算使用固定的5个线程来处理这些所有的Client,也就意味着一个线程可能负责处理多个Socket。 我原本的打算是一个Client轮询地去读取每个Socket的字节流,后来发现行不通,在读取第一个Socket的输入流时就卡住了,完全是阻塞的。 代码如下: ``` public void handle() throws IOException, InvalidProtocolException { byte[] buf = new byte[1024]; StringBuilder sb = new StringBuilder(); int readLength; try { for(;;){ readLength = in.read(buf); if (readLength > 0) { sb.append(new String(buf, 0, readLength)); } else { break; } } parse(sb.toString()); } catch (IOException e1) { throw e1; } catch (InvalidProtocolException e2) { throw e2; } } ``` 在in.read这一行处,完全被阻塞,无法做到轮询。 那么是否意味着使用BIO时,一个线程只能处理一个Socket,直到这个Socket关闭? 那么在很多个客户端的情况下,线程数不会爆炸多吗? 求解。
java多线程使用sleep后线程停止不再执行
环境:jdk1.7 程序代码: 启动线程: ``` import java.text.SimpleDateFormat; import java.util.Date; public class CTThread implements Runnable{ @Override public void run() { Thread upds = new Thread(new UpdateDSThread()); Thread uphs = new Thread(new UpdateHSThread()); uphs.setPriority(7); Thread dh = new Thread(new DeleteHistory()); Thread check = new Thread(new CheckStatus()); Thread cp = new Thread(new CheckPool()); // Thread sc = new Thread(new SCThread()); upds.start(); uphs.start(); dh.start(); check.start(); cp.start(); // sc.start(); SimpleDateFormat dd = new SimpleDateFormat("yyyy-MM-dd: HH:mm:ss"); while(true){ System.out.println("线程检查~~~·"+dd.format(new Date())); System.out.println("upds:"+upds.getState()+upds.getPriority()); System.out.println("check:"+check.getState()+check.getPriority()); System.out.println("uphs:"+uphs.getState()+uphs.getPriority()); System.out.println("dh:"+dh.getState()+dh.getPriority()); System.out.println("cp:"+cp.getState()+cp.getPriority()); // System.out.println("sc:"+sc.isAlive()+sc.getPriority()); if(!upds.isAlive()){ upds = new Thread(new UpdateDSThread()); upds.start(); } if(!check.isAlive()){ check = new Thread(new CheckStatus()); check.start(); } if(!uphs.isAlive()){ uphs = new Thread(new UpdateHSThread()); uphs.start(); } if(!dh.isAlive()){ dh = new Thread(new DeleteHistory()); dh.start(); } if(!cp.isAlive()){ cp = new Thread(new CheckPool()); cp.start(); } // if(!sc.isAlive()){ // sc = new Thread(new SCThread()); // sc.start(); // } try { Thread.sleep(1000*13); } catch (InterruptedException e) { e.printStackTrace(); } } } } ``` 线程1: ``` import entity.Device; import hibernate.Search; import main.UpdateDeviceStatus; import java.util.Iterator; import java.util.List; public class UpdateHSThread implements Runnable { @Override public void run() { // TODO Auto-generated method stub System.out.println("iops线程"); while(true){ Device device; UpdateDeviceStatus update = new UpdateDeviceStatus(); Search search = new Search(); List devicelist = search.getALL("Device"); Iterator deviceitor = devicelist.iterator(); long startTime = System.currentTimeMillis(); try { System.out.println("iops设备数量:" + devicelist.size()); while (deviceitor.hasNext()) { device = (Device) deviceitor.next(); System.out.println("HS连接设备:" + device.getIp()); System.out.println("HSstart"); update.updateHS(device.getFlag(),device.getcinfo()); System.out.println("HSover"); } } catch (Exception e) { e.printStackTrace(); }finally { } long endTime = System.currentTimeMillis(); try { long time = endTime - startTime; Thread.sleep(1000*10); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } } ``` 线程2: ``` import entity.Device; import hibernate.Search; import main.UpdateDeviceStatus; import java.util.Iterator; import java.util.List; public class UpdateDSThread implements Runnable { @Override public void run() { // TODO Auto-generated method stub while (true) { System.out.println("DS进程~~~~~"); Device device = new Device(); UpdateDeviceStatus update = new UpdateDeviceStatus(); Search search = new Search(); List devicelist = search.getALL("Device"); Iterator deviceitor = devicelist.iterator(); while (deviceitor.hasNext()) { device = (Device) deviceitor.next(); try { System.out.println("DS连接设备" + device.getIp()); System.out.println("DSstart"); update.updateDS(device.getFlag(),device.getcinfo()); System.out.println("DSover"); } catch (Exception e) { e.printStackTrace(); } finally { } } try { Thread.sleep(1000 * 60); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } } ``` 一共有两个类似的线程,程序刚刚启动的时候一切正常,但是当过一段时间后会有一个线程不再进行循环,用Thread.getState()查询的线程状态是TIMED_WAITING。 没有异常输出,重启程序后一切正常,两个线程都会每隔规定时间循环一次,但是经过一段时间后又会变成只有一个线程正常循环,另一个停在那。从程序启动到出问题的时间不固定,有的时候一周才出一次,有的时候一小时内就会出。 查不出来是什么问题,求大神解答,挺急的 ``` 线程检查~~~·2017-12-13: 17:19:05 upds:TIMED_WAITING5 check:TIMED_WAITING5 uphs:TIMED_WAITING7 dh:TIMED_WAITING5 cp:TIMED_WAITING5 iops设备数量:4 HS连接设备:null HSstart HSover HS连接设备:172.10.4.101 HSstart connect 172.10.4.101 success 实时iops 写入iops HSover HS连接设备:172.10.4.200 HSstart connect 172.10.4.200 success 实时iops 写入iops HSover HS连接设备:172.10.4.200 HSstart connect 172.10.4.200 success 实时iops 写入iops HSover 清理历史记录 171213171915 171212171915 startdelete 10 deleteover dh over~~~ 线程检查~~~·2017-12-13: 17:19:18 upds:TIMED_WAITING5 check:TIMED_WAITING5 uphs:TIMED_WAITING7 dh:TIMED_WAITING5 cp:TIMED_WAITING5 iops设备数量:4 HS连接设备:null HSstart HSover HS连接设备:172.10.4.101 HSstart connect 172.10.4.101 success 实时iops 写入iops HSover HS连接设备:172.10.4.200 HSstart connect 172.10.4.200 success 实时iops 写入iops HSover HS连接设备:172.10.4.200 HSstart connect 172.10.4.200 success 实时iops 写入iops HSover 线程检查~~~·2017-12-13: 17:19:31 upds:TIMED_WAITING5 check:TIMED_WAITING5 uphs:TIMED_WAITING7 dh:TIMED_WAITING5 cp:TIMED_WAITING5 iops设备数量:4 HS连接设备:null HSstart HSover HS连接设备:172.10.4.101 HSstart connect 172.10.4.101 success 实时iops 写入iops HSover HS连接设备:172.10.4.200 HSstart connect 172.10.4.200 success 实时iops 写入iops HSover HS连接设备:172.10.4.200 HSstart connect 172.10.4.200 success 实时iops 写入iops HSover 检查池容量 iops设备数量:4 HS连接设备:null HSstart HSover HS连接设备:172.10.4.101 HSstart connect 172.10.4.101 success 实时iops 线程检查~~~·2017-12-13: 17:19:44 upds:TIMED_WAITING5 check:TIMED_WAITING5 uphs:TIMED_WAITING7 dh:TIMED_WAITING5 cp:TIMED_WAITING5 线程检查~~~·2017-12-13: 17:19:57 upds:TIMED_WAITING5 check:TIMED_WAITING5 uphs:TIMED_WAITING7 dh:TIMED_WAITING5 cp:TIMED_WAITING5 DS进程~~~~~ DS连接设备null DSstart DSover DS连接设备172.10.4.101 DSstart systeminfo connect 172.10.4.101 success 存储池容量 connect 172.10.4.101 success DSover DS连接设备172.10.4.200 DSstart systeminfo connect 172.10.4.200 success 存储池容量 connect 172.10.4.200 success DSover DS连接设备172.10.4.200 DSstart systeminfo connect 172.10.4.200 success 存储池容量 connect 172.10.4.200 success DSover 清理历史记录 171213172002 171212172002 startdelete 8 deleteover dh over~~~ 线程检查~~~·2017-12-13: 17:20:10 upds:TIMED_WAITING5 check:TIMED_WAITING5 uphs:TIMED_WAITING7 dh:TIMED_WAITING5 cp:TIMED_WAITING5 线程检查~~~·2017-12-13: 17:20:23 upds:TIMED_WAITING5 check:TIMED_WAITING5 uphs:TIMED_WAITING7 dh:TIMED_WAITING5 cp:TIMED_WAITING5 检查池容量 线程检查~~~·2017-12-13: 17:20:36 upds:TIMED_WAITING5 check:TIMED_WAITING5 uphs:TIMED_WAITING7 dh:TIMED_WAITING5 cp:TIMED_WAITING5 设备检查 CS连接设备172.10.4.101 connect 172.10.4.101 success nodecanister canistersinfo online online online online drivesinfo psusinfo batteriesinfo CS连接设备172.10.4.200 connect 172.10.4.200 success nodecanister canistersinfo online null drivesinfo CS连接设备172.10.4.200 connect 172.10.4.200 success nodecanister canistersinfo online null drivesinfo 清理历史记录 171213172049 171212172049 startdelete 10 deleteover dh over~~~ 线程检查~~~·2017-12-13: 17:20:49 upds:TIMED_WAITING5 check:TIMED_WAITING5 uphs:TIMED_WAITING7 dh:TIMED_WAITING5 cp:TIMED_WAITING5 DS进程~~~~~ DS连接设备null DSstart DSover DS连接设备172.10.4.101 DSstart systeminfo connect 172.10.4.101 success 存储池容量 connect 172.10.4.101 success DSover DS连接设备172.10.4.200 DSstart systeminfo connect 172.10.4.200 success 存储池容量 connect 172.10.4.200 success 线程检查~~~·2017-12-13: 17:21:02 upds:TIMED_WAITING5 check:TIMED_WAITING5 uphs:TIMED_WAITING7 dh:TIMED_WAITING5 cp:TIMED_WAITING5 DSover DS连接设备172.10.4.200 DSstart systeminfo connect 172.10.4.200 success 存储池容量 connect 172.10.4.200 success DSover 线程检查~~~·2017-12-13: 17:21:15 upds:TIMED_WAITING5 check:TIMED_WAITING5 uphs:TIMED_WAITING7 dh:TIMED_WAITING5 cp:TIMED_WAITING5 线程检查~~~·2017-12-13: 17:21:28 upds:TIMED_WAITING5 check:TIMED_WAITING5 uphs:TIMED_WAITING7 dh:TIMED_WAITING5 cp:TIMED_WAITING5 检查池容量 清理历史记录 171213172136 171212172136 startdelete 8 deleteover dh over~~~ 线程检查~~~·2017-12-13: 17:21:41 upds:TIMED_WAITING5 check:TIMED_WAITING5 uphs:TIMED_WAITING7 dh:TIMED_WAITING5 cp:TIMED_WAITING5 线程检查~~~·2017-12-13: 17:21:54 upds:TIMED_WAITING5 check:TIMED_WAITING5 uphs:TIMED_WAITING7 dh:TIMED_WAITING5 cp:TIMED_WAITING5 DS进程~~~~~ DS连接设备null DSstart DSover DS连接设备172.10.4.101 DSstart systeminfo connect 172.10.4.101 success 存储池容量 connect 172.10.4.101 success DSover DS连接设备172.10.4.200 DSstart systeminfo connect 172.10.4.200 success 存储池容量 connect 172.10.4.200 success DSover DS连接设备172.10.4.200 DSstart systeminfo connect 172.10.4.200 success 存储池容量 connect 172.10.4.200 success DSover 线程检查~~~·2017-12-13: 17:22:07 upds:TIMED_WAITING5 check:TIMED_WAITING5 uphs:TIMED_WAITING7 dh:TIMED_WAITING5 cp:TIMED_WAITING5 ``` 上面是我自己程序中的输出,可以看到刚开始DS和HS两个线程是循环运行的,但是到后面就只有DS了
Java多线程下载的问题
package com.briup.day24; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.RandomAccessFile; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; public class DownloadThread extends Thread { private static final Object o=new Object(); private int id; private String path; private int startIndex; private int endIndex; public DownloadThread(int id, String path, int startIndex, int endIndex) { // TODO Auto-generated constructor stub this.id = id; this.path = path; this.startIndex = startIndex; this.endIndex = endIndex; } @Override public void run() { // TODO Auto-generated method stub URL url; try { File file = new File(id + ".txt"); int lastProgress = 0; if (file.exists()) { BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(file))); lastProgress = Integer.parseInt(br.readLine()); startIndex+=lastProgress; br.close(); } url = new URL(path); HttpURLConnection connection = (HttpURLConnection) url.openConnection(); connection.setRequestMethod("GET"); connection.setReadTimeout(8000); connection.setConnectTimeout(8000); connection.setRequestProperty("Range", "bytes="+startIndex+"-"+endIndex); connection.connect(); if (connection.getResponseCode() == HttpURLConnection.HTTP_PARTIAL) { InputStream inputStream = connection.getInputStream(); byte[] arr = new byte[1024]; int len = -1; int total = lastProgress; RandomAccessFile raf = new RandomAccessFile("download.jpg", "rwd"); raf.seek(startIndex); RandomAccessFile raff = null; while ((len = inputStream.read(arr)) != -1) { // 写入到本地文件中 sleep(100); raf.write(arr, 0, len); total += len; System.out.println("第" + id + "条线程下载了" + total); raff = new RandomAccessFile(file, "rwd"); raff.write((total + "").getBytes()); } raff.close(); raf.close(); synchronized (o) { Main.finishedThreadCount++; if(Main.finishedThreadCount==Main.THREADCOUNT) { //删除 for(int i=0;i<Main.THREADCOUNT;i++) { File f=new File(i+".txt"); f.delete(); } } } } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } package com.briup.day24; import java.io.File; import java.io.IOException; import java.io.RandomAccessFile; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; import javax.net.ssl.HttpsURLConnection; /** * 多线程断点下载 1、先去磁盘上创建一个要下载的文件大小一样的空文件 2、计算每个线程的下载区间 * * @author yuxiangrousigaifan * */ public class Main { public static final String PATH = "https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1508931223542&di=69e33a551ab94504d1124b9ba28ab3c2&imgtype=0&src=http%3A%2F%2Fimgsrc.baidu.com%2Fimgad%2Fpic%2Fitem%2F0bd162d9f2d3572c329d50f18113632762d0c3a4.jpg"; public static final int THREADCOUNT = 3; public static int finishedThreadCount = 0; public static void main(String[] args) throws IOException { URL url = new URL(PATH); HttpURLConnection connection = (HttpURLConnection) url.openConnection(); connection.setRequestMethod("GET"); connection.setReadTimeout(8000); connection.setConnectTimeout(8000); connection.connect(); if (connection.getResponseCode() == HttpURLConnection.HTTP_OK) { int size = connection.getContentLength(); System.out.println(size); File file = new File("download.jpg"); RandomAccessFile raf = new RandomAccessFile(file, "rwd"); raf.setLength(size); raf.close(); // int length = size / THREADCOUNT; for (int id = 0; id < THREADCOUNT; id++) { int startIndex = id * length; int endIndex = (id + 1) * length - 1; if (id == THREADCOUNT - 1) { endIndex = size - 1; } System.out.println("编号为" + id + "的线程的现在区间是" + startIndex + "----" + endIndex); new DownloadThread(id, PATH, startIndex, endIndex).start(); } } } } 用这个程序下载之后 在工程下面一直保留三个临时下载记录 删除不掉 ,但是我在线程类最后用了delete()方法呀 求大佬们解答
Java写交易客户端(多线程、对象数据传送等简单问题)
有如下几个类: 1、Ticker类 //此Ticker为简单java类,其属性与服务器传来的json字段对应,通过Decoder类反系列化json //反系列化以后的数据,用以做逻辑判断,符合逻辑,则向服务器发出某种请求 public class Ticker implements Serializable { private static final long serialVersionUID = 2015022601L; private volatile Double buy; private volatile Double contractId; public void setBuy(Double buy) { this.buy = buy; } public void setContractId(Double contractId) { this.contractId = contractId; } } public Double getBuy() { return buy; } public BigDecimal getContractId() { return contractId; } public Ticker() { super(); } public Ticker( Double buy, Double contractId) { this.buy = buy; this.contractId = contractId; } } 2、Decoder类 //此类接收服务器传来的json(msg字符串),采用Gson将其反系列化 //此msg消息一直不断推送过来,比如第一次推送{buy:100,contractId:20},下一次可能是{buy:50,contractId:305} public class Decoder implements Abc{ @Override public void onReceive(String msg){ System.out.println(msg); if (msg.contains("ticker")) { Gson gson=new Gson(); Ticker ticker=gson.fromJson(msg, Ticker.class); //反系列化后得到的数据存于ticker对象 } } } 3、Test类 //此类利用反系列化后的数据进行判断,然后向服务器发出某些请求 public class Test{ 此类里需要用到Decoder里得到的ticker对象的buy及contractId属性值, 比如此类一直在做以下判断 if (buy>contractId){ 向服务器发出一次请求 } } 问题: (1),Test类怎么才能得到Decoder类里实例化的ticker对象的属性值(buy,contractId),是在Ticker加上一个构造方法?还是在Decoder类里写一个方法?或者其他?请给出实际代码。 (付:这是一个线程间通讯的问题么?) (2),Decoder类一直每秒几次的转换服务器推送来的json,每一次得到的ticker对象地址不一样,其ticker只有最近一个的属性有用,这样是不是产生了大量的垃圾,还是说虽然地址不一样,但后产生的ticker自动覆盖了前面的ticker对象? (3),如果此程序采用多线程,同时还使用SWT写了一个UI类,是否要再写一个类用来更新ticker对象的属性到UI界面上(或者采用Eclipse数据绑定的办法)? 现在相当于: Decoder类一直不断在进行json转换, UI类一直在把ticker对象的属性数据更新到UI界面(或者用其他办法更新上去), Test类也一直在使用ticker的属性值进行数据的逻辑判断, 此程序是否应该是至少三个线程?那具体怎么实现多线程(每个类都实现Runnable接口?)?主方法是该放在UI类里,还是放在客服端里(Test类是否可作为客服端)? 请请给出具体多线程实现的代码? (4)如果Test类用于逻辑判断的属性值buy和contractId不采用Decoder类里产生的,而是去UI界面上再次取得,那这个取得过程是否与(2)问的解决办法一样? 真心求教,成功发财了发个大红包!
Java swing多线程实现聊天程序阻塞问题
1、在用swing写一个能够动态添加客户端的socket通信程序,即服务端用 一个异步线程持续监听新的客户端连接,如果有新的连接就新建一个客户端线 程来监听客户端,接收或者发送给客户端信息。 ```java //这是监听客户端连接的线程: new Thread(new Runnable() { @Override public void run() { // 异步线程持续监听端口连接 while (true){ if (server.isClosed()){ // 服务器一旦关闭,就跳出循环 break; } Socket temp = null; try { temp = server.accept(); JOptionPane.showMessageDialog(null,"连接建立成功,客户端端口号为:" +temp.getPort()); // 为每一个连接建立一个异步线程 Connection con = new Connection(temp); con.start(); connections.add(con); sockets.add(temp); } catch (IOException ex) { ex.printStackTrace(); } } } }).start(); ``` 这是客户端线程类: ```java class Connection extends Thread{ Socket socket; BufferedReader reader; PrintWriter writer; public Connection(Socket socket){ this.socket = socket; } @Override public void run() { System.out.println("来了!"); try { reader = new BufferedReader(new InputStreamReader(socket.getInputStream())); writer = new PrintWriter(socket.getOutputStream()); // 第一次连接,先写出已经存在的联系人 writer.println("还没有联系人"); // 再读取新建联系人的名字 String clientName = reader.readLine(); System.out.println("客户端名字:" +clientName); reader.close(); } catch (IOException e) { e.printStackTrace(); } /* while (true){ try { if (socket.isConnected() == false){ break; } } catch (Exception e) { e.printStackTrace(); } }*/ } } ``` 这是客户端启动时执行的方法: ```java @Override public void windowOpened(WindowEvent e) { // 窗口打开就建立连接 try { socket = new Socket("localhost",3030); reader = new BufferedReader(new InputStreamReader(socket.getInputStream())); writer = new PrintWriter(socket.getOutputStream()); } catch (IOException ex) { JOptionPane.showMessageDialog(null,"服务器未开启,不能连接,请关闭此客户端!"); } /* 连接一旦建立需要立刻执行的事情 * 1、向服务器发送该客户端的名字 * 2、获取其他已经存在的客户端名字 * */ try { System.out.println(reader.readLine()); writer.println(clientName); } catch (IOException ex) { ex.printStackTrace(); } } ``` 每次一到这个windowOpen方法的System.out.println(reader.readLine());这里就卡死,没有报错,直接卡住。 看了网上说什么readline()会因为没读到数据阻塞,所以猜想是服务端发送数据时一直没有发出来,不过没有找到解决办法,这是卡住时的情况截图 ![图片说明](https://img-ask.csdn.net/upload/201911/08/1573184051_750205.png)
关于java多线程的问题
本人写一个小测试,构想是开一条主线程不断循环扫数据库中的任务,每拿到一条任务开2个子线程分发给500个用户, 我的想法是在子线程的构造参数里面把所有用户传入,然后run方法里面加同步块来控制用户的减少,每发送一个用户就把该用户移除,但是现在不会同步这一块,求助,贴上代码: MainThread public class ScanDB implements Runnable{ public void run() { List<String> list1=new ArrayList<String>(); List<String> list2=new ArrayList<String>(); for(int t=0;t<3;t++){ for (int j=0;j<10;j++){ list2.add("用户"+(t*10+j)); } list1.addAll(list2); } childThread childThread=new childThread(list1,1); childThread childThread2=new childThread(list1,1); Thread t1=new Thread(childThread); t1.setName("Thread1"); t1.start(); Thread t2=new Thread(childThread2); t2.setName("Thread2"); t2.start(); } } ChildThread: public class childThread implements Runnable{ private List<String> users; private int schdule; private int count; public childThread(List<String> users, int schdule) { this.users = users; this.schdule = schdule; this.count=users.size(); } public void run() { while (count>0) { sendMail(); } } private void sendMail(){ //求助部分 count--; } }
在java线程的run方法里在new多个线程可以吗?
在java线程的run方法里在new多个线程可以吗,我要写个定时器定时执行一个线程,可以不可以在这个线程的run方法里在new多个线程执行任务,执行的结果在run方法里汇总然后返回 [b]问题补充:[/b] to 和你在一起:我用了TimerTask,然后用join等每个线程执行完后返回结果好像可以吗
请问JAVA ODBC编程ResultSet多线程的问题
使用ResultSet取得SQL查询的结果,并对每个next进行处理,写入文件中: File c=new File("E:\\test.txt"); FileWriter x = new FileWriter(c); Statement stat = conn.createStatement(); ResultSet resultSet = stat.executeQuery(sql); String result = ""; while(resultSet.next()) { for (int i = 0; i < 100; i++) { result = result + resultSet.getString(DEF_COLUMN(i)); } x.write(result); } ... 然后觉得速度太慢,想要把字符串处理放到线程中(以下简写) LinkedBlockingQueu<String> queue = new LinkedBlockingQueu<String>(20); thread 1: do { String result = ""; for (int i = 0; i < 100; i++) { result = result + resultSet.getString(DEF_COLUMN(i)); } queue.put(result); }while(resultSet.next()); thread2: do { String result = queue.take(); x.write(result); }while(!queue.isEmpty()); 像上面的形式,当thread1开启一个的时候没有问题。但当开启多个thread1时,resultSet在for循环时不能被其他线程执行next否则报错,没办法只能加锁,这样虽然使用了多线程,但thread1被强制转换成单线程,速度并没有多大提升。所以我想问有没有提升resultSet的fetch速度的好方法。 ps:使用ResultSet localSet = reultSet; 尝试了一下,哈哈,localSet只是resultSet的一个引用,并没有把数据复制到localSet中,localSet.next()的时候另一个线程还是会报错。这种办法不可行。
java C/S socket通信多线程问题
问题如下:客户端起十个线程,每个线程向服务端发一万次信息,服务端起五个线程,分别接收客户端的请求,每收到一次信息,数据库里把请求次数加一。执行完成后,验证一下数据库里请求次数是否为十万次.使用了Mybatis框架来操作数据库,代码如下. 问题是:如果不加数据库操作,是可以完整收到10W个信息.但是如果加上数据库操作,就会少收到3000条左右的信息,问题在哪?怎么解决?或者用其他什么方法可以解决. 客户端: ``` package homework8; import java.io.OutputStreamWriter; import java.net.InetAddress; import java.net.Socket; public class Client { Socket clientSocket; OutputStreamWriter outputStreamWriter ; public static void main(String[] args) throws Exception{ new Client().connect(); } class MyThread extends Thread { public void run(){ int i; for(i=0;i<10000;i++){ try{ System.out.println(Thread.currentThread().getName()+"执行第"+i+"次发送"); outputStreamWriter.write("哈哈"+"\r\n"); outputStreamWriter.flush(); }catch(Exception e){ e.printStackTrace(); } } } } public void connect() throws Exception{ clientSocket =new Socket(InetAddress.getLocalHost(),8088); outputStreamWriter=new OutputStreamWriter(clientSocket.getOutputStream()); for(int k=0;k<10;k++){ MyThread thread=new MyThread(); thread.start(); } } } ``` 服务器: ``` package homework8; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.net.ServerSocket; import java.net.Socket; import org.apache.ibatis.session.SqlSession; import util.MybatisUtil; public class Server1 { static Server1 server; BufferedReader bufferedReader; public int times; public int i=1; ServerThread st; ServerSocket ss; private static final int SERVER_PORT =8088; //接收客户端请求 并启动线程 public void update(int k) throws Exception{ SqlSession sqlSession = null; try{ sqlSession = MybatisUtil.getSqlSession(); sqlSession.update("requestNamespace.update",k); sqlSession.commit(); }catch(Exception e){ e.printStackTrace(); sqlSession.rollback(); throw e; }finally{ MybatisUtil.closeSqlSession(); } } public void receive() throws Exception{ ss=new ServerSocket(SERVER_PORT); try { while (true) { Socket socket = ss.accept(); bufferedReader=new BufferedReader(new InputStreamReader(socket.getInputStream())); st=new ServerThread(); Thread thread1 = new Thread(st, "SyncThread1"); Thread thread2 = new Thread(st, "SyncThread2"); Thread thread3 = new Thread(st, "SyncThread3"); Thread thread4 = new Thread(st, "SyncThread4"); Thread thread5 = new Thread(st, "SyncThread5"); thread1.start(); thread2.start(); thread3.start(); thread4.start(); thread5.start(); } }catch (IOException e) { }finally { ss.close(); } } //创建线程的内部类 class ServerThread implements Runnable { public void run() { try { String line="a"; while (!line.equals("qwerty")) { synchronized (this) { line=bufferedReader.readLine(); System.out.println(Thread.currentThread().getName()+"接收了第"+i+"个"+line); i++; update(i); } } }catch (Exception e) { e.printStackTrace(); System.out.println("接收完毕"); try{ ss.close(); }catch(Exception x){ x.printStackTrace(); } } } } //启动服务器 public static void main(String[] args)throws Exception { server=new Server1(); server.receive(); } } ``` Mybatis工具类 ``` package util; import java.io.IOException; import java.io.Reader; import java.sql.Connection; import org.apache.ibatis.io.Resources; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactoryBuilder; public class MybatisUtil { private static ThreadLocal<SqlSession> threadLocal=new ThreadLocal<SqlSession>(); private static SqlSessionFactory sqlSessionFactory; //加载mybatis配置文件 static{ try { Reader reader=Resources.getResourceAsReader("mybatis.config.xml"); sqlSessionFactory=new SqlSessionFactoryBuilder().build(reader); } catch (IOException e) { e.printStackTrace(); throw new RuntimeException(e); } } //获取线程 public static SqlSession getSqlSession(){ //从当前线程中获取SqlSession对象 SqlSession sqlSession = threadLocal.get(); if(sqlSession == null){ //在SqlSessionFactory非空的情况下,获取SqlSession对象 sqlSession = sqlSessionFactory.openSession(); //将SqlSession对象与当前线程绑定在一起 threadLocal.set(sqlSession); } //返回SqlSession对象 return sqlSession; } //关闭SqlSession与当前线程分开 public static void closeSqlSession(){ //从当前线程中获取SqlSession对象 SqlSession sqlSession = threadLocal.get(); //如果SqlSession对象非空 if(sqlSession != null){ //关闭SqlSession对象 sqlSession.close(); //分开当前线程与SqlSession对象的关系 threadLocal.remove(); } } public static void main(String[] args) { Connection conn = MybatisUtil.getSqlSession().getConnection(); System.out.println(conn!=null?"连接成功":"连接失败"); } } ```
java多线程与并发的线程之间通信的问题
既然每个线程有自己的工作内存为什么我执行下面代码的时候主内存变量的更改能够影响线程 为什么会执行到 System.out.println(num+"*****************线程终止************"); 还有为什么我把System.out.println(num);一行注释掉就永远停止不了了 那么Java到底在什么时间执行read和load、store和write ``` public class CourrTest02 extends Thread{ private static long num=0; private boolean a=true; @Override public void run() { while(num!=10001){ // System.out.println(num); } System.out.println(num+"*****************线程终止************"); } public static void main(String[] args) throws InterruptedException { boolean b=true; CourrTest02 c1=new CourrTest02(); c1.start(); Thread.sleep(1000); for(int i=0;i<10000;i++){ c1.num=10001; } } } ```
关于Java多线程的问题,求大神解决
一个简单的例子,一个线程类代表客户,一个线程类代表厨师, 厨师每做好5个包子两个客户就吃,吃完再做。 运行时出现 java.lang.IllegalMonitorStateException错误,而且每次都只是一个人在吃。 实在是弄不明白了。。。 代码如下: public class Resource { //锁对象,静态资源,可以被公开访问 static Object lock = new Object(); //包子容器,静态资源,可以被公开访问 static List<String> container = new ArrayList<String>(); } public class Producer implements Runnable { @Override public void run() { // TODO Auto-generated method stub while (true) { synchronized ("") { if (Resource.container.size() == 5) { Resource.lock.notifyAll();// 唤醒所有在等待Resource.lock这把锁的线程 } else { System.out.println("开始制作包子"); // 模拟耗时 try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } Resource.container.add("包子"); } } } } } public class Cutstom implements Runnable { @Override public void run() { // TODO Auto-generated method stub while (true) { synchronized ("") { // 容器中没有包子了,吃货们就要等待包子 if (Resource.container.size() == 0) { System.out.println("包子吃光啦,老板上包子"); try { Resource.lock.wait();// 释放自己持有了锁,并开始等待被notify } catch (InterruptedException e) { e.printStackTrace(); } } else { // 模拟耗时 try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } // 移除吃过的包子 System.out.println("吃货:" + Thread.currentThread().getName() + "吃包子"); Resource.container.remove(0); } } } } } public class Test { public static void main(String[] args) { // TODO Auto-generated method stub Cutstom cutstom = new Cutstom() ; new Thread(cutstom,"a").start() ; new Thread(cutstom,"b").start() ; Producer producer = new Producer() ; new Thread(producer,"c").start(); } } console: Exception in thread "a" 包子吃光啦,老板上包子 java.lang.IllegalMonitorStateException at java.lang.Object.wait(Native Method) at java.lang.Object.wait(Unknown Source) at food.Cutstom.run(Cutstom.java:15) at java.lang.Thread.run(Unknown Source) 开始制作包子 开始制作包子 开始制作包子 开始制作包子 开始制作包子 Exception in thread "c" java.lang.IllegalMonitorStateException at java.lang.Object.notifyAll(Native Method) at food.Producer.run(Producer.java:10) at java.lang.Thread.run(Unknown Source) 吃货:b吃包子 吃货:b吃包子 吃货:b吃包子 吃货:b吃包子 吃货:b吃包子 包子吃光啦,老板上包子 Exception in thread "b" java.lang.IllegalMonitorStateException at java.lang.Object.wait(Native Method) at java.lang.Object.wait(Unknown Source) at food.Cutstom.run(Cutstom.java:15) at java.lang.Thread.run(Unknown Source)
java多线程,统计每个线程执行次数
# 执行代码后算出来总是多3 ``` package work2; public class Part implements Runnable{ private int n = 800; private int i = 1; @Override public void run() { // TODO Auto-generated method stub int m = 0; while(i <= n){ if(i <= n) { m++; } sell(); } System.out.println(Thread.currentThread().getName()+"生产了:"+m+"个"); } public synchronized void sell(){ if(i <= n){ try { Thread.sleep(1); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } if(i <= n){ System.out.println(Thread.currentThread().getName()+ "生产第"+ i++ +"个零件"); } } } } ``` ``` package work2; public class WorkShop { public static void main(String [] args){ Part part = new Part(); Thread thread1 = new Thread(part, "第一生产车间"); Thread thread2 = new Thread(part, "第二生产车间"); Thread thread3 = new Thread(part, "第三生产车间"); Thread thread4 = new Thread(part, "第四生产车间"); thread1.start(); thread2.start(); thread3.start(); thread4.start(); } } ```
java多线程问题请教
<div class="iteye-blog-content-contain" style="font-size: 14px;"> <p>大家好,小弟刚学多线程,有个概念一直没搞懂,之前一直说如果在方法在创建多个实例对象然后调用其方法不会有线程安全问题,就是struts2 都说每个请求创建了一个新的实例就不会有线程问题。</p> <p> </p> <p>那我做了个例子,运行结果一直都有问题,特请教</p> <p> </p> <p>有2个类</p> <p> </p> <p>public class Outputter2 {</p> <p>//输出name<br> public void output(String name) {<br>  int len = name.length();   <br>   for (int i = 0; i &lt; len; i++) {<br>    System.out.print(name.charAt(i));<br>   }<br>   System.out.println();<br>   }</p> <p>}</p> <p> </p> <p>///////////////////////////</p> <p>public class Outputter4 implements Runnable {</p> <p> private String name;<br> <br> public Outputter4(String name){<br>  this.name = name;<br> }<br> <br> @Override<br> public void run() {</p> <p>  while (true) {<br>   try {<br>    Thread.sleep(1000);<br>   } catch (InterruptedException e) {<br>    // TODO Auto-generated catch block<br>    e.printStackTrace();<br>   }<br>   //System.out.println(name);<br>   new Outputter2().output(name);</p> <p>  }<br>  <br> }<br> <br> public static void main(String[] args) {</p> <p>//每次都创建新的Outputter4<br>  new Thread(new Outputter4("aaaa")).start();<br>  new Thread(new Outputter4("bbbb")).start();<br> }</p> <p>}</p> <p> </p> <p>打印效果,不正确:</p> <p>aaaa<br>bbbb<br>abbbb<br>aaa<br>bbbb<br>aaaa<br>baaaa<br>bbb<br>aaaa<br><br> 请帮忙解释,我一直没弄明白错在那里?</p> <p> 是不是由于name引起的,如果name不使用实例变量,怎么传递?</p> <p>  在方法里使用对象变量是安全的是怎么解释?</p> <p> </p> <p>谢谢!!!!</p> </div>
Java小白求救啊!!!
package com.shuai.plane; import java.awt.Color; import java.awt.Graphics; import java.awt.event.KeyAdapter; import java.awt.event.KeyEvent; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.image.BufferedImage; import java.lang.ref.PhantomReference; import java.util.ArrayList; import java.util.List; import javax.swing.JPanel; //JAVA中游戏面板:JPanel /* * 自定义游戏面板 * 1.写一个类继承JPanel * 2.创建构造方法,初始化游戏面板的属性 * * 画图的步骤 * 1.在类中定义图片,并取名 * 2.在构造方法中调用工具类(Photo)初始化图片 * 3.在画图方法paint中,画图片(paint是专门的画图方法) * */ public class GamePanel extends JPanel{ //创建一个集合,用来存放敌机(敌机的大本营) List<EnemyPlane> arrays = new ArrayList<>(); //创建一个集合,用来放英雄机的弹药 List<HeroFire> HFire = new ArrayList<>(); //创建一个集合,用来放敌机的弹药 List<EnemyFire> EnFire = new ArrayList<>(); //创建英雄机的对象 HeroPlane heroPlane = new HeroPlane(); //创建敌机的对象 EnemyPlane enemyPlane = new EnemyPlane(); //写一个线程,让程序跑起来 //写一个方法,启动线程 public void action() { new Thread() { public void run() { //定义一个变量控制敌机出现的数量 int a = 0; int b = 20; //写一个死循环,让程序一直运行 while(true) { //让敌机出现在面板上 if(a == b) { MakeEP(); a = 0; } //让敌机移动 epMove(); //让英雄机子弹出现在面板上 if(a == 0) { MakeHeroFire(); } //让英雄机的子弹动起来 HeroFireMove(); //让敌机的子弹出现在面板上 //MakeEnemyFire(); //让敌机的子弹动起来 //EnemyFireMove(); //重绘布局(刷新页面) repaint(); try { this.sleep(30); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } a++; } } }.start(); } //写一个方法,让敌机移动 public void epMove() { for(int i = 0; i < arrays.size(); i++) { EnemyPlane enemyPlane = arrays.get(i); enemyPlane.y += 10; if(enemyPlane.y > 800) { arrays.remove(enemyPlane); } //EnemyFire enemyFire = EnFire.get(i); //enemyFire.y += 15; } } //写一个方法,用来生产敌机,并把它放进集合中 void MakeEP() { //创建敌机 EnemyPlane enemyPlane = new EnemyPlane(); //创建敌机的子弹 //EnemyFire enemyFire = new EnemyFire(enemyPlane.x, enemyPlane.y); //把敌机加到大本营中(集合) arrays.add(enemyPlane); //EnFire.add(enemyFire); } //写一个方法,生产英雄机的弹药,并把它放进英雄机的弹药库 void MakeHeroFire() { for(int i = 0; i < arrays.size(); i++) { HeroFire heroFire = new HeroFire(heroPlane.x + 15, heroPlane.y, 0); HFire.add(heroFire); HeroFire heroFire2 = new HeroFire(heroPlane.x + 78, heroPlane.y, 2); HFire.add(heroFire2); HeroFire heroFire3 = new HeroFire(heroPlane.x + 48, heroPlane.y - 20, 1); HFire.add(heroFire3); } } //写一个方法让英雄机子弹移动 public void HeroFireMove() { for(int i = 0; i < HFire.size(); i++) { HeroFire heroFire = HFire.get(i); if(heroFire.dir == 0) { heroFire.x -= 1; } if(heroFire.dir == 2) { heroFire.x += 1; } heroFire.y -= 10; // if(heroFire.y < -heroFire.h) { // HFire.remove(heroFire); // } } } //写一个方法生产敌机的弹药,并放进敌机的弹药库 void MakeEnemyFire() { EnemyFire enemyFire = new EnemyFire(enemyPlane.x, enemyPlane.y); EnFire.add(enemyFire); } //让敌机的子弹动起来 void EnemyFireMove() { for(int i = 0; i < EnFire.size(); i++) { EnFire.get(i).y += 15; } } //定义背景图 BufferedImage bgp; //创建构造方法,初始化面板 public GamePanel(GameFrame gameFrame) { //设置面板的背景 //setBackground(Color.cyan); //通过工具类(Photo)获取图片 bgp = Photo.getImage("/Img/bg1.jpg"); /* * 使用鼠标监听器(固定格式) */ //1.创建鼠标适配器 //这是一个匿名内部类 MouseAdapter adapter = new MouseAdapter() { //2.确定需要的鼠标监听事件 /* * 鼠标监听事件: * 1.mouseMoved();监听鼠标移动事件 * 2.mouseCliked();监听鼠标单击事件(鼠标按下后松开才会被监听,按下不会被监听) * 3.mousePressed();监听鼠标按下去的事件(只要鼠标按下就会被监听) * 4.mouseEntered();监听鼠标移入游戏界面的事件 * 5.mouseExited();监听鼠标移出游戏界面的事件 * * MouseEvevt:鼠标的事件,记录鼠标做的事情 * */ @Override //当鼠标在游戏界面移动时,会触发此方法 public void mouseMoved(MouseEvent e) { //让英雄机跟着鼠标移动,就让英雄机的横纵坐标等于鼠标的横纵坐标 //获取鼠标的坐标(getX();获取鼠标的横坐标, getY();获取鼠标的纵坐标) int mx = e.getX(); int my = e.getY(); //让英雄机移动到鼠标的位置(英雄机移动到鼠标的位置,是英雄机的行为,可以在英雄机中定义方法) //此时英雄机依然不会移动,其实英雄机的坐标已经改变,但是没有把英雄机绘制到新的坐标,需要刷新页面 //heroPlane.move(mx, my); heroPlane.x = mx - heroPlane.w/2; heroPlane.y = my - heroPlane.h/2; //刷新页面,将英雄机绘制到新的页面 //重新调用paint方法(re 表示重新调用) repaint(); } @Override //当鼠标在游戏界面单击时,会触发此方法 public void mouseClicked(MouseEvent e) { System.out.println("~~~~~~~鼠标单击了"); } @Override //当鼠标在游戏界面按下时,会触发此方法 public void mousePressed(MouseEvent e) { System.out.println("!!!!!!!!鼠标被按下了"); } @Override //当鼠标移入游戏界面时,会触发此方法 public void mouseEntered(MouseEvent e) { System.out.println("**************鼠标被移出"); } @Override //当鼠标移出游戏界面时,会触发此方法 public void mouseExited(MouseEvent e) { System.out.println("**************鼠标被移入"); } }; //3.将适配器加入到监听器中(固定格式) addMouseListener(adapter); addMouseMotionListener(adapter); /* * 使用键盘适配器(固定模式) */ // 1.创建键盘适配器 KeyAdapter key = new KeyAdapter() { // 2.确定需要监听的键盘事件 @Override //当键盘按下时,会触发此方法 public void keyPressed(KeyEvent e) { //监听键盘的按键(每一个按键都对应有一个数字) //获取按键的数字 int a = e.getKeyCode(); //KeyEvent.VK_?;是表示指定的按键对应的数字 if(a == KeyEvent.VK_A || a == KeyEvent.VK_LEFT) { if((heroPlane.x -= 10) < -heroPlane.w/2) { heroPlane.x = 0 - heroPlane.w/2; } }else if(a == KeyEvent.VK_D || a == KeyEvent.VK_RIGHT) { if((heroPlane.x += 10) > 600 - heroPlane.w/2) { heroPlane.x = 600 - heroPlane.w/2; } }else if(a == KeyEvent.VK_W || a == KeyEvent.VK_UP) { if((heroPlane.y -= 10) < 0) { heroPlane.y = 0; } }else if(a == KeyEvent.VK_S || a == KeyEvent.VK_DOWN) { if((heroPlane.y += 10) > 800 - heroPlane.h) { heroPlane.y = 800 - heroPlane.h; } } //重绘,将英雄机画到新的位置上 repaint(); /* if(e.getKeyChar() == 'a') { if((heroPlane.x -= 10) < -heroPlane.w/2) { heroPlane.x = 0 - heroPlane.w/2; } } if(e.getKeyChar() == 'd') { if((heroPlane.x += 10) > 600 - heroPlane.w/2) { heroPlane.x = 600 - heroPlane.w/2; } } if(e.getKeyChar() == 'w') { if((heroPlane.y -= 10) < 0) { heroPlane.y = 0; } } if(e.getKeyChar() == 's') { if((heroPlane.y += 10) > 800 - heroPlane.h) { heroPlane.y = 800 - heroPlane.h; } } //重绘,将英雄机画到新的位置上 repaint(); */ } }; // 3.将适配器加入到窗体的监听器中(加到面板的键盘监听器中是没有用的) //可以在创建面板对象时,把窗体对象传过来,然后把键盘适配器添加到窗体的键盘监听器中 //需要面板的构造器添加参数,并指定类型 gameFrame.addKeyListener(key); } //专门画图的方法,重写于JComponent类(JPanel的父类) //画图的方法:(画图时一定要注意图片的尺寸) // 格式: g.drawImage(图片, 横坐标, 纵坐标, 宽度, 高度, 当转换了更多图片是要通知的对象) // 画图时如果不设定图片的大小,图片显示就是原图的大小 @Override public void paint(Graphics g) { //g.drawImage(img, x, y, observer); //横纵坐标是设置图片左上角的坐标,设置图片的大小 g.drawImage(bgp, 0, 0, 600, 800, null); //在paint中画图是有顺序的,先画的在下面一层,先画的会被后画的覆盖 //给敌机画图 //已经把敌机放入集合中了,使用遍历绘制敌机 for(int i = 0; i < arrays.size(); i++) { EnemyPlane enemyPlane = arrays.get(i); g.drawImage(enemyPlane.img, enemyPlane.x, enemyPlane.y, enemyPlane.w, enemyPlane.h, null); } //给英雄机画图 g.drawImage(heroPlane.img, heroPlane.x, heroPlane.y, heroPlane.w, heroPlane.h, null); //把英雄机的弹药画进面板 for(int i = 0; i < HFire.size(); i++) { HeroFire heroFire = HFire.get(i); g.drawImage(heroFire.img, heroFire.x, heroFire.y, heroFire.w, heroFire.h, null); } //把敌机的子弹画进面板中 // for(int i = 0; i < EnFire.size(); i++) { // EnemyFire enemyFire = EnFire.get(i); // g.drawImage(enemyFire.img, enemyFire.x, enemyFire.y, enemyFire.w, enemyFire.h, null); // } } } ![图片说明](https://img-ask.csdn.net/upload/202003/20/1584711414_269752.png)![图片说明](https://img-ask.csdn.net/upload/202003/20/1584711424_683016.png)![图片说明](https://img-ask.csdn.net/upload/202003/20/1584711438_860998.png)![图片说明](https://img-ask.csdn.net/upload/202003/20/1584711451_113820.jpg) ![图片说明](https://img-ask.csdn.net/upload/202003/20/1584711743_593343.png) 图一是运行时操作的画面,如果移动鼠标或者按着键盘不放(应该是飞机移动太快的时候),就会出现下面的画面,会一次出现多个子弹(我就的是鼠标移动时刷新的太快,但是线程里面是限制了时间的,难道是鼠标或者键盘和县线程里面重复刷新了???不会啊,求救啊!!!)。还有,截图代码中,如果把圈出来的判断代码放出来,游戏界面就会出现圈起来的样子(最左边的子弹向上走到一定高度就会变成两个,每次都是在那个高度,并且只有最左边的子弹会变化。)(我就的可能是集合删除后子弹的位置改变了,如果用LinkedList会不会好点?求救!!!)
ThreadPoolExecutor 线程执行到一半消失??
做一个导入功能,用ThreadPoolExecutor 进行多线程导入10000条数据,10个线程,一个线程任务每次处理100条数据。 结果只有9000+数据正常入库,添加数据的业务没报错。查日志后发现,每页开始导入的日志有100条,但每页结束的日志只有90多。感觉有部分线程在执行任务时没有执行到最后就消失了。 问:为什么线程会执行到一半消失,后台没报错日志。怎么避免这种情况? ``` /** * rowList 中有一万条学生数据 * 用多线程入库,每100条为一页,一页数据一个线程执行 */ public void import(List<List<String>> rowList){ Integer page = total/100; if ((total%100)>0){ page=page+1; } LinkedBlockingQueue linkedBlockingQueue = new LinkedBlockingQueue(); //初始化线程池 ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(10,10,60, TimeUnit.SECONDS,linkedBlockingQueue); try { //计数分页数据 for(int i=0 ;i<page;i++){ int start = i*100; int end = start+100; if (end>rowList.size()){ end = rowList.size(); //分页数据 List<List<String>> lists =rowList.subList(start,end); ImportStu importStu = new ImportStu(lists,i); //执行线程 threadPoolExecutor.execute(importStu); } }catch (Exception e){ log.error("学生导入线程池执行出错:{}",e.getMessage(),e); } threadPoolExecutor.shutdown(); } /** *线程执行的任务,数据入库 */ class ImportStu implements Runnable{ private List<List<String>> lists; private String page; public ImportStu(List<List<String>> rowList,int page){ this.lists = rowList; this.page = page; } @Override public void run() { log.info("学生导入,第{}页开始导入,Thread:{}",page,Thread.currentThread().getId()) for(int i=0;i<lists.size(); i++ ){ try{ log.info("学生导入,开始执行第{}页第{}行,Thread:{}",page,i,Thread.currentThread().getId()); //单条数据入库业务 stuService.add(lists.get(i)); }catch (Exception e){ log.error("添加数据失败:{}",e.getMessage(),e); } } } log.info("学生导入,第{}页导入完毕,Thread:{}",page,Thread.currentThread().getId()) } ```
Java多线程问题?
[code="java"] package com.zzf.thread; public class Test_03 { public static void main(String[] args) { // TODO 自动生成方法存根 TxtThread tt = new TxtThread(); new Thread(tt).start(); new Thread(tt).start(); new Thread(tt).start(); new Thread(tt).start(); } } class TxtThread implements Runnable { int num = 20; String str = new String(); public void run() { while (true) { synchronized (str) {//这里的锁? if (num > 0) { try { Thread.sleep(10); } catch (Exception e) { e.getMessage(); } System.out.println(Thread.currentThread().getName() + "this is " + num--); } } } } } [/code] 输出结果: Thread-0this is 20 Thread-0this is 19 Thread-0this is 18 Thread-0this is 17 Thread-0this is 16 Thread-0this is 15 Thread-0this is 14 Thread-0this is 13 Thread-0this is 12 Thread-0this is 11 Thread-0this is 10 Thread-0this is 9 Thread-3this is 8 Thread-3this is 7 Thread-3this is 6 Thread-3this is 5 Thread-3this is 4 Thread-3this is 3 Thread-3this is 2 Thread-3this is 1 我不明白的是:TxtThread也是一个类,每创建一个它的对象就会拥有它的属性,因此num,str不是共享的,不存在访问冲突的情况 另外代码中synchronized (str) //这里获取的锁是哪一个对象的?我不是太懂synchronized的使用方法和原理
java多线程同步问题,小弟百撕不得其解,特来求助!
多线程共享同一资源,同一张票卖出了多张!同步方法,同步代码块都没用。 问题:编写三各类Ticket、SealWindow、TicketSealCenter分别代表票信息、售票窗口、售票中心。售票中心分配一定数量的票,由若干个售票窗口进行出售,利用你所学的线程知识来模拟此售票过程。 public class ThreadDemo { public static void main(String[] args) { Thread t1 = new Thread(new SealWindow(),"1号售票窗口"); Thread t2 = new Thread(new SealWindow(),"2号售票窗口"); Thread t3 = new Thread(new SealWindow(),"3号售票窗口"); Thread t4 = new Thread(new SealWindow(),"4号售票窗口"); Thread t5 = new Thread(new SealWindow(),"5号售票窗口"); t1.start(); t2.start(); t3.start(); t4.start(); t5.start(); } } class Ticket { private int id; public int getId() { return id; } public void setId(int id) { this.id = id; } } class SealWindow implements Runnable { private ReentrantLock lock = new ReentrantLock(); @Override public void run() { sellTicket(); } public synchronized void sellTicket() { TicketSealCenter tsc = TicketSealCenter.getInstance(); List<Ticket> tickets = tsc.getTickets(); while (!tickets.isEmpty()) { Iterator<Ticket> it = tickets.iterator(); Ticket ticket = it.next(); System.out.println(Thread.currentThread().getName() + "...." + "卖了一张票,id为" + "..." + ticket.getId()); tickets.remove(ticket); } } } // 只有一个售票中心,所以把它设置成单例 class TicketSealCenter { private static List<Ticket> tickets = new ArrayList<Ticket>(); private int ticketNum = 100; private TicketSealCenter() { // 给每张票设置一个唯一的ID号 setIdToTicket(tickets); } private static TicketSealCenter tsc = new TicketSealCenter(); // 提供一个公有方法,获取售票中心对象 public static TicketSealCenter getInstance() { return tsc; } private void setIdToTicket(List<Ticket> tickets2) { for (int i = 1; i <= ticketNum; i++) { Ticket ticket = new Ticket(); ticket.setId(i); tickets.add(ticket); } } public List<Ticket> getTickets() { return tickets; } }
关于Java与android线程多次start()问题?
请教如题, 晚上吃完饭没事想到个问题,测试了一下也不明不白的。。望解答。 我在android项目里面写了一个按钮,按钮里面开启一个简单的线程 如下。 Thread thread = new Thread(runnable); thread.start(); 线程里面也不需要做什么事情,就打印了一些数据,我每按一次就打印一次。想请教一下,我每按一次是开启的新线程,多个线程同时工作呢,还是在原线程里面增加了队列依次进行工作? 自己测试和网上找了一下也还没怎么明白。求高手~
在中国程序员是青春饭吗?
今年,我也32了 ,为了不给大家误导,咨询了猎头、圈内好友,以及年过35岁的几位老程序员……舍了老脸去揭人家伤疤……希望能给大家以帮助,记得帮我点赞哦。 目录: 你以为的人生 一次又一次的伤害 猎头界的真相 如何应对互联网行业的「中年危机」 一、你以为的人生 刚入行时,拿着傲人的工资,想着好好干,以为我们的人生是这样的: 等真到了那一天,你会发现,你的人生很可能是这样的: ...
《MySQL 性能优化》之理解 MySQL 体系结构
本文介绍 MySQL 的体系结构,包括物理结构、逻辑结构以及插件式存储引擎。
程序员请照顾好自己,周末病魔差点一套带走我。
程序员在一个周末的时间,得了重病,差点当场去世,还好及时挽救回来了。
Python+OpenCV实时图像处理
目录 1、导入库文件 2、设计GUI 3、调用摄像头 4、实时图像处理 4.1、阈值二值化 4.2、边缘检测 4.3、轮廓检测 4.4、高斯滤波 4.5、色彩转换 4.6、调节对比度 5、退出系统 初学OpenCV图像处理的小伙伴肯定对什么高斯函数、滤波处理、阈值二值化等特性非常头疼,这里给各位分享一个小项目,可通过摄像头实时动态查看各类图像处理的特点,也可对各位调参、测试...
2020年一线城市程序员工资大调查
人才需求 一线城市共发布岗位38115个,招聘120827人。 其中 beijing 22805 guangzhou 25081 shanghai 39614 shenzhen 33327 工资分布 2020年中国一线城市程序员的平均工资为16285元,工资中位数为14583元,其中95%的人的工资位于5000到20000元之间。 和往年数据比较: yea...
为什么猝死的都是程序员,基本上不见产品经理猝死呢?
相信大家时不时听到程序员猝死的消息,但是基本上听不到产品经理猝死的消息,这是为什么呢? 我们先百度搜一下:程序员猝死,出现将近700多万条搜索结果: 搜索一下:产品经理猝死,只有400万条的搜索结果,从搜索结果数量上来看,程序员猝死的搜索结果就比产品经理猝死的搜索结果高了一倍,而且从下图可以看到,首页里面的五条搜索结果,其实只有两条才是符合条件。 所以程序员猝死的概率真的比产品经理大,并不是错...
害怕面试被问HashMap?这一篇就搞定了!
声明:本文以jdk1.8为主! 搞定HashMap 作为一个Java从业者,面试的时候肯定会被问到过HashMap,因为对于HashMap来说,可以说是Java集合中的精髓了,如果你觉得自己对它掌握的还不够好,我想今天这篇文章会非常适合你,至少,看了今天这篇文章,以后不怕面试被问HashMap了 其实在我学习HashMap的过程中,我个人觉得HashMap还是挺复杂的,如果真的想把它搞得明明白...
毕业5年,我问遍了身边的大佬,总结了他们的学习方法
我问了身边10个大佬,总结了他们的学习方法,原来成功都是有迹可循的。
python爬取百部电影数据,我分析出了一个残酷的真相
2019年就这么匆匆过去了,就在前几天国家电影局发布了2019年中国电影市场数据,数据显示去年总票房为642.66亿元,同比增长5.4%;国产电影总票房411.75亿元,同比增长8.65%,市场占比 64.07%;城市院线观影人次17.27亿,同比增长0.64%。 看上去似乎是一片大好对不对?不过作为一名严谨求实的数据分析师,我从官方数据中看出了一点端倪:国产票房增幅都已经高达8.65%了,为什...
推荐10个堪称神器的学习网站
每天都会收到很多读者的私信,问我:“二哥,有什么推荐的学习网站吗?最近很浮躁,手头的一些网站都看烦了,想看看二哥这里有什么新鲜货。” 今天一早做了个恶梦,梦到被老板辞退了。虽然说在我们公司,只有我辞退老板的份,没有老板辞退我这一说,但是还是被吓得 4 点多都起来了。(主要是因为我掌握着公司所有的核心源码,哈哈哈) 既然 4 点多起来,就得好好利用起来。于是我就挑选了 10 个堪称神器的学习网站,推...
这些软件太强了,Windows必装!尤其程序员!
Windows可谓是大多数人的生产力工具,集娱乐办公于一体,虽然在程序员这个群体中都说苹果是信仰,但是大部分不都是从Windows过来的,而且现在依然有很多的程序员用Windows。 所以,今天我就把我私藏的Windows必装的软件分享给大家,如果有一个你没有用过甚至没有听过,那你就赚了????,这可都是提升你幸福感的高效率生产力工具哦! 走起!???? NO、1 ScreenToGif 屏幕,摄像头和白板...
阿里面试,面试官没想到一个ArrayList,我都能跟他扯半小时
我是真的没想到,面试官会这样问我ArrayList。
曾经优秀的人,怎么就突然不优秀了。
职场上有很多辛酸事,很多合伙人出局的故事,很多技术骨干被裁员的故事。说来模板都类似,曾经是名校毕业,曾经是优秀员工,曾经被领导表扬,曾经业绩突出,然而突然有一天,因为种种原因,被裁员了,...
C语言荣获2019年度最佳编程语言
关注、星标公众号,不错过精彩内容作者:黄工公众号:strongerHuang近日,TIOBE官方发布了2020年1月编程语言排行榜单。我在前面给过一篇文章《2019年11月C语言接近Ja...
大学四年因为知道了这32个网站,我成了别人眼中的大神!
依稀记得,毕业那天,我们导员发给我毕业证的时候对我说“你可是咱们系的风云人物啊”,哎呀,别提当时多开心啦????,嗯,我们导员是所有导员中最帅的一个,真的???? 不过,导员说的是实话,很多人都叫我大神的,为啥,因为我知道这32个网站啊,你说强不强????,这次是绝对的干货,看好啦,走起来! PS:每个网站都是学计算机混互联网必须知道的,真的牛杯,我就不过多介绍了,大家自行探索,觉得没用的,尽管留言吐槽吧???? 社...
良心推荐,我珍藏的一些Chrome插件
上次搬家的时候,发了一个朋友圈,附带的照片中不小心暴露了自己的 Chrome 浏览器插件之多,于是就有小伙伴评论说分享一下我觉得还不错的浏览器插件。 我下面就把我日常工作和学习中经常用到的一些 Chrome 浏览器插件分享给大家,随便一个都能提高你的“生活品质”和工作效率。 Markdown Here Markdown Here 可以让你更愉快的写邮件,由于支持 Markdown 直接转电子邮...
看完这篇HTTP,跟面试官扯皮就没问题了
我是一名程序员,我的主要编程语言是 Java,我更是一名 Web 开发人员,所以我必须要了解 HTTP,所以本篇文章就来带你从 HTTP 入门到进阶,看完让你有一种恍然大悟、醍醐灌顶的感觉。 最初在有网络之前,我们的电脑都是单机的,单机系统是孤立的,我还记得 05 年前那会儿家里有个电脑,想打电脑游戏还得两个人在一个电脑上玩儿,及其不方便。我就想为什么家里人不让上网,我的同学 xxx 家里有网,每...
史上最全的IDEA快捷键总结
现在Idea成了主流开发工具,这篇博客对其使用的快捷键做了总结,希望对大家的开发工作有所帮助。
阿里程序员写了一个新手都写不出的低级bug,被骂惨了。
这种新手都不会范的错,居然被一个工作好几年的小伙子写出来,差点被当场开除了。
谁是华为扫地僧?
是的,华为也有扫地僧!2020年2月11-12日,“养在深闺人不知”的华为2012实验室扫地僧们,将在华为开发者大会2020(Cloud)上,和大家见面。到时,你可以和扫地僧们,吃一个洋...
AI 没让人类失业,搞 AI 的人先失业了
最近和几个 AI 领域的大佬闲聊 根据他们讲的消息和段子 改编出下面这个故事 如有雷同 都是巧合 1. 老王创业失败,被限制高消费 “这里写我跑路的消息实在太夸张了。” 王葱葱哼笑一下,把消息分享给群里。 阿杰也看了消息,笑了笑。在座几位也都笑了。 王葱葱是个有名的人物,21岁那年以全额奖学金进入 KMU 攻读人工智能博士,累计发表论文 40 余篇,个人技术博客更是成为深度学习领域内风向标。 ...
2020年,冯唐49岁:我给20、30岁IT职场年轻人的建议
点击“技术领导力”关注∆每天早上8:30推送 作者|Mr.K 编辑| Emma 来源|技术领导力(ID:jishulingdaoli) 前天的推文《冯唐:职场人35岁以后,方法论比经验重要》,收到了不少读者的反馈,觉得挺受启发。其实,冯唐写了不少关于职场方面的文章,都挺不错的。可惜大家只记住了“春风十里不如你”、“如何避免成为油腻腻的中年人”等不那么正经的文章。 本文整理了冯...
一份王者荣耀的英雄数据报告
咪哥杂谈本篇阅读时间约为 6 分钟。1前言前一阵写了关于王者的一些系列文章,从数据的获取到数据清洗,数据落地,都是为了本篇的铺垫。今天来实现一下,看看不同维度得到的结论。2环境准备本次实...
作为一名大学生,如何在B站上快乐的学习?
B站是个宝,谁用谁知道???? 作为一名大学生,你必须掌握的一项能力就是自学能力,很多看起来很牛X的人,你可以了解下,人家私底下一定是花大量的时间自学的,你可能会说,我也想学习啊,可是嘞,该学习啥嘞,不怕告诉你,互联网时代,最不缺的就是学习资源,最宝贵的是啥? 你可能会说是时间,不,不是时间,而是你的注意力,懂了吧! 那么,你说学习资源多,我咋不知道,那今天我就告诉你一个你必须知道的学习的地方,人称...
那些年,我们信了课本里的那些鬼话
教材永远都是有错误的,从小学到大学,我们不断的学习了很多错误知识。 斑羚飞渡 在我们学习的很多小学课文里,有很多是错误文章,或者说是假课文。像《斑羚飞渡》: 随着镰刀头羊的那声吼叫,整个斑羚群迅速分成两拨,老年斑羚为一拨,年轻斑羚为一拨。 就在这时,我看见,从那拨老斑羚里走出一只公斑羚来。公斑羚朝那拨年轻斑羚示意性地咩了一声,一只半大的斑羚应声走了出来。一老一少走到伤心崖,后退了几步,突...
一个程序在计算机中是如何运行的?超级干货!!!
强烈声明:本文很干,请自备茶水!???? 开门见山,咱不说废话! 你有没有想过,你写的程序,是如何在计算机中运行的吗?比如我们搞Java的,肯定写过这段代码 public class HelloWorld { public static void main(String[] args) { System.out.println("Hello World!"); } ...
【蘑菇街技术部年会】程序员与女神共舞,鼻血再次没止住。(文末内推)
蘑菇街技术部的年会,别开生面,一样全是美女。
那个在阿里养猪的工程师,5年了……
简介: 在阿里,走过1825天,没有趴下,依旧斗志满满,被称为“五年陈”。他们会被授予一枚戒指,过程就叫做“授戒仪式”。今天,咱们听听阿里的那些“五年陈”们的故事。 下一个五年,猪圈见! 我就是那个在养猪场里敲代码的工程师,一年多前我和20位工程师去了四川的猪场,出发前总架构师慷慨激昂的说:同学们,中国的养猪产业将因为我们而改变。但到了猪场,发现根本不是那么回事:要个WIFI,没有;...
为什么程序猿都不愿意去外包?
分享外包的组织架构,盈利模式,亲身经历,以及根据一些外包朋友的反馈,写了这篇文章 ,希望对正在找工作的老铁有所帮助
Java校招入职华为,半年后我跑路了
何来 我,一个双非本科弟弟,有幸在 19 届的秋招中得到前东家华为(以下简称 hw)的赏识,当时秋招签订就业协议,说是入了某 java bg,之后一系列组织架构调整原因等等让人无法理解的神操作,最终毕业前夕,被通知调往其他 bg 做嵌入式开发(纯 C 语言)。 由于已至于校招末尾,之前拿到的其他 offer 又无法再收回,一时感到无力回天,只得默默接受。 毕业后,直接入职开始了嵌入式苦旅,由于从未...
立即提问