高分求解---有个问题从大四开始就在困扰我,一直不知道怎么解决!

时间:2022-12-17 14:35:33
减言之,我就是想阻塞、唤醒某条指定的线程
比如,创建了10个普通的线程,ID从1到10,线程之间不存在类似于“生产者消费者、哲学家进餐”之类的共享资源约束;
   当从控制台输入"2 wait"的时候,使ID为2的线程处于阻塞状态(如果它原先的状态是就绪),不影响其他线程;
  当从控制台输入"3 wake"的时候,使ID为3的线程处于就绪状态(如果它原先的状态是阻塞),不影响其他线程。

17 个解决方案

#1


仔细想一下,真不知道怎么搞,帮顶,求高手。

#2


这个问题痛点是,如何通过统一的控制台,提供信息给多个线程。

#3


用线程池比较好处理吧。

#4


我做的是一个socket文件上传和接收的,用的线程池。大概意思是这样的:服务器段总带宽大小为5M/秒,每个用户上传一个文件,服务器端开启一个线程,socket接收文件的速度是5M/总共上传文件的数量。如果是文件小的优先,那么就把文件大的线程暂停,等小的传递完毕,再把大文件的那个线程打开。

#5


用一个控制中心接收输入。
在线程中用一个变量表示要wait。
当收到wait命令时修改这个变量的值表示要wait,
当收到wake命令时调用线程的notify。
或者用Seamphore的机制也可以,就是调用release和acquire.

#6


搞了半天毫无结果,主要问题看来还是如3楼所说,怎么去主动控制多线程

#7


做了个假的阻塞,用flag来控制,当要wait的时候flag=false,当wake的时候flag=true。其实线程还是在运行
public void run() {
while (!Thread.currentThread().isInterrupted()) {
while (flag) {
try {
//do something
Thread.sleep(2000);
System.out.println(this.id);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}

#8


后来想想如果这样的话不知道啊算是阻塞
public void run() {
while (!Thread.currentThread().isInterrupted()) {
try {
if(!flag){
this.sleep(1000);
}

System.out.println(this.id);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

}
}

就是无法把sleep改成wait(),不知道为什么,请大神求解

#9


应该首先想到用
线程池

#10


终于能回复了
稍微做了下,不知道是否满足要求,一共两个类。因为电脑的问题,我指做了3个线程,10个就卡死了
package com.thread;

import java.util.*;
import java.util.Map.Entry;
import java.io.*;

public class TestThread {
HashMap<Integer, Td> hm;
String no;

public static void main(String[] args) {
TestThread tt = new TestThread();
while (true) {
tt.showMenu();

try {
BufferedReader strin = new BufferedReader(
new InputStreamReader(System.in));
tt.no = strin.readLine();
} catch (IOException e) {
e.printStackTrace();
}

switch (tt.no) {
case "1":
tt.showWaitThread(tt.hm);
System.out.println("请输入要选择的线程号:");
try {
BufferedReader strin = new BufferedReader(
new InputStreamReader(System.in));
tt.no = strin.readLine();
} catch (IOException e) {
e.printStackTrace();
}
tt.setWait(Integer.parseInt(tt.no));
break;
case "2":
tt.showWakeThread(tt.hm);
System.out.println("请输入要选择的线程号:");
try {
BufferedReader strin = new BufferedReader(
new InputStreamReader(System.in));
tt.no = strin.readLine();
} catch (IOException e) {
e.printStackTrace();
}
tt.setWake(Integer.parseInt(tt.no));
break;
case "3":
// 显示所有线程的情况
tt.showThread(tt.hm);
break;
case "4":
System.exit(0);

}
}
}

public TestThread() {
hm = new HashMap<Integer, Td>();
for (int n = 1; n <= 3; n++) {
Td t = new Td(n);
hm.put(n, t);
t.start();
}
}

public void showMenu() {
System.out.println("菜单");
System.out.println("1 阻塞线程");
System.out.println("2 唤醒线程");
System.out.println("3 显示线程情况");
System.out.println("4 退出");
System.out.println("请输入你要的选择:");
}

public void showThread(HashMap hm) {
Iterator a = hm.entrySet().iterator();
while (a.hasNext()) {
Entry t = (Entry) a.next();
System.out.println("第  " + t.getKey() + " 号线程的状态是: "
+ ((Td) t.getValue()).getState());
}
}

public void showWaitThread(HashMap hm) {
Iterator a = hm.entrySet().iterator();
while (a.hasNext()) {
Entry t = (Entry) a.next();
if (((Td) t.getValue()).getState().toString().equals("RUNNABLE")) {
System.out.println("第  " + t.getKey() + " 号线程的状态是: "
+ ((Td) t.getValue()).getState());
}
}
}

public void showWakeThread(HashMap hm) {
Iterator a = hm.entrySet().iterator();
while (a.hasNext()) {
Entry t = (Entry) a.next();
if (((Td) t.getValue()).getState().toString().equals("WAITING")) {
System.out.println("第  " + t.getKey() + " 号线程的状态是: "
+ ((Td) t.getValue()).getState());
}
}
}



public void setWait(int n) {

hm.get(n).setFlag(false);

}

public void setWake(int n) {
Td tmp = hm.get(n);
tmp.setFlag(true);
synchronized (tmp) {
tmp.notify();
}
}
}

package com.thread;

public class Td extends Thread {

int id;
boolean flag;

public boolean isFlag() {
return flag;
}

public void setFlag(boolean flag) {
this.flag = flag;
}

public Td(int id) {
this.id = id;
flag = true;
}

@Override
public void run() {
synchronized (this) {

while (!Thread.currentThread().isInterrupted()) {
try {
if (!flag) {
wait();
}
//sleep(3000);
// System.out.print(this.id);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}

}

#11


http://bbs.csdn.net/topics/390484059

#12


如果 就是想阻塞 然后唤醒指定的线程
#11楼的大哥 有给出不错的答案

#13


线程池呢.用.

#14


引用 10 楼 gmh0421 的回复:
终于能回复了
稍微做了下,不知道是否满足要求,一共两个类。因为电脑的问题,我指做了3个线程,10个就卡死了
package com.thread;

import java.util.*;
import java.util.Map.Entry;
import java.io.*;

public class TestThread {
HashMap<Integer, Td> hm;
String no;

public static void main(String[] args) {
TestThread tt = new TestThread();
while (true) {
tt.showMenu();

try {
BufferedReader strin = new BufferedReader(
new InputStreamReader(System.in));
tt.no = strin.readLine();
} catch (IOException e) {
e.printStackTrace();
}

switch (tt.no) {
case "1":
tt.showWaitThread(tt.hm);
System.out.println("请输入要选择的线程号:");
try {
BufferedReader strin = new BufferedReader(
new InputStreamReader(System.in));
tt.no = strin.readLine();
} catch (IOException e) {
e.printStackTrace();
}
tt.setWait(Integer.parseInt(tt.no));
break;
case "2":
tt.showWakeThread(tt.hm);
System.out.println("请输入要选择的线程号:");
try {
BufferedReader strin = new BufferedReader(
new InputStreamReader(System.in));
tt.no = strin.readLine();
} catch (IOException e) {
e.printStackTrace();
}
tt.setWake(Integer.parseInt(tt.no));
break;
case "3":
// 显示所有线程的情况
tt.showThread(tt.hm);
break;
case "4":
System.exit(0);

}
}
}

public TestThread() {
hm = new HashMap<Integer, Td>();
for (int n = 1; n <= 3; n++) {
Td t = new Td(n);
hm.put(n, t);
t.start();
}
}

public void showMenu() {
System.out.println("菜单");
System.out.println("1 阻塞线程");
System.out.println("2 唤醒线程");
System.out.println("3 显示线程情况");
System.out.println("4 退出");
System.out.println("请输入你要的选择:");
}

public void showThread(HashMap hm) {
Iterator a = hm.entrySet().iterator();
while (a.hasNext()) {
Entry t = (Entry) a.next();
System.out.println("第  " + t.getKey() + " 号线程的状态是: "
+ ((Td) t.getValue()).getState());
}
}

public void showWaitThread(HashMap hm) {
Iterator a = hm.entrySet().iterator();
while (a.hasNext()) {
Entry t = (Entry) a.next();
if (((Td) t.getValue()).getState().toString().equals("RUNNABLE")) {
System.out.println("第  " + t.getKey() + " 号线程的状态是: "
+ ((Td) t.getValue()).getState());
}
}
}

public void showWakeThread(HashMap hm) {
Iterator a = hm.entrySet().iterator();
while (a.hasNext()) {
Entry t = (Entry) a.next();
if (((Td) t.getValue()).getState().toString().equals("WAITING")) {
System.out.println("第  " + t.getKey() + " 号线程的状态是: "
+ ((Td) t.getValue()).getState());
}
}
}



public void setWait(int n) {

hm.get(n).setFlag(false);

}

public void setWake(int n) {
Td tmp = hm.get(n);
tmp.setFlag(true);
synchronized (tmp) {
tmp.notify();
}
}
}

package com.thread;

public class Td extends Thread {

int id;
boolean flag;

public boolean isFlag() {
return flag;
}

public void setFlag(boolean flag) {
this.flag = flag;
}

public Td(int id) {
this.id = id;
flag = true;
}

@Override
public void run() {
synchronized (this) {

while (!Thread.currentThread().isInterrupted()) {
try {
if (!flag) {
wait();
}
//sleep(3000);
// System.out.print(this.id);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}

}

Sorry,童鞋,暂时不能给你分,这个程序一跑,我的CPU占用率已经超过90%了。

#15


好吧,除了这点,能满足你的要求不?

#16


引用 15 楼 gmh0421 的回复:
好吧,除了这点,能满足你的要求不?

不行,太卡了;如果5个以上的话,基本上就要死机;你能否再想别的好办法?

#17


你想做什么....

#1


仔细想一下,真不知道怎么搞,帮顶,求高手。

#2


这个问题痛点是,如何通过统一的控制台,提供信息给多个线程。

#3


用线程池比较好处理吧。

#4


我做的是一个socket文件上传和接收的,用的线程池。大概意思是这样的:服务器段总带宽大小为5M/秒,每个用户上传一个文件,服务器端开启一个线程,socket接收文件的速度是5M/总共上传文件的数量。如果是文件小的优先,那么就把文件大的线程暂停,等小的传递完毕,再把大文件的那个线程打开。

#5


用一个控制中心接收输入。
在线程中用一个变量表示要wait。
当收到wait命令时修改这个变量的值表示要wait,
当收到wake命令时调用线程的notify。
或者用Seamphore的机制也可以,就是调用release和acquire.

#6


搞了半天毫无结果,主要问题看来还是如3楼所说,怎么去主动控制多线程

#7


做了个假的阻塞,用flag来控制,当要wait的时候flag=false,当wake的时候flag=true。其实线程还是在运行
public void run() {
while (!Thread.currentThread().isInterrupted()) {
while (flag) {
try {
//do something
Thread.sleep(2000);
System.out.println(this.id);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}

#8


后来想想如果这样的话不知道啊算是阻塞
public void run() {
while (!Thread.currentThread().isInterrupted()) {
try {
if(!flag){
this.sleep(1000);
}

System.out.println(this.id);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

}
}

就是无法把sleep改成wait(),不知道为什么,请大神求解

#9


应该首先想到用
线程池

#10


终于能回复了
稍微做了下,不知道是否满足要求,一共两个类。因为电脑的问题,我指做了3个线程,10个就卡死了
package com.thread;

import java.util.*;
import java.util.Map.Entry;
import java.io.*;

public class TestThread {
HashMap<Integer, Td> hm;
String no;

public static void main(String[] args) {
TestThread tt = new TestThread();
while (true) {
tt.showMenu();

try {
BufferedReader strin = new BufferedReader(
new InputStreamReader(System.in));
tt.no = strin.readLine();
} catch (IOException e) {
e.printStackTrace();
}

switch (tt.no) {
case "1":
tt.showWaitThread(tt.hm);
System.out.println("请输入要选择的线程号:");
try {
BufferedReader strin = new BufferedReader(
new InputStreamReader(System.in));
tt.no = strin.readLine();
} catch (IOException e) {
e.printStackTrace();
}
tt.setWait(Integer.parseInt(tt.no));
break;
case "2":
tt.showWakeThread(tt.hm);
System.out.println("请输入要选择的线程号:");
try {
BufferedReader strin = new BufferedReader(
new InputStreamReader(System.in));
tt.no = strin.readLine();
} catch (IOException e) {
e.printStackTrace();
}
tt.setWake(Integer.parseInt(tt.no));
break;
case "3":
// 显示所有线程的情况
tt.showThread(tt.hm);
break;
case "4":
System.exit(0);

}
}
}

public TestThread() {
hm = new HashMap<Integer, Td>();
for (int n = 1; n <= 3; n++) {
Td t = new Td(n);
hm.put(n, t);
t.start();
}
}

public void showMenu() {
System.out.println("菜单");
System.out.println("1 阻塞线程");
System.out.println("2 唤醒线程");
System.out.println("3 显示线程情况");
System.out.println("4 退出");
System.out.println("请输入你要的选择:");
}

public void showThread(HashMap hm) {
Iterator a = hm.entrySet().iterator();
while (a.hasNext()) {
Entry t = (Entry) a.next();
System.out.println("第  " + t.getKey() + " 号线程的状态是: "
+ ((Td) t.getValue()).getState());
}
}

public void showWaitThread(HashMap hm) {
Iterator a = hm.entrySet().iterator();
while (a.hasNext()) {
Entry t = (Entry) a.next();
if (((Td) t.getValue()).getState().toString().equals("RUNNABLE")) {
System.out.println("第  " + t.getKey() + " 号线程的状态是: "
+ ((Td) t.getValue()).getState());
}
}
}

public void showWakeThread(HashMap hm) {
Iterator a = hm.entrySet().iterator();
while (a.hasNext()) {
Entry t = (Entry) a.next();
if (((Td) t.getValue()).getState().toString().equals("WAITING")) {
System.out.println("第  " + t.getKey() + " 号线程的状态是: "
+ ((Td) t.getValue()).getState());
}
}
}



public void setWait(int n) {

hm.get(n).setFlag(false);

}

public void setWake(int n) {
Td tmp = hm.get(n);
tmp.setFlag(true);
synchronized (tmp) {
tmp.notify();
}
}
}

package com.thread;

public class Td extends Thread {

int id;
boolean flag;

public boolean isFlag() {
return flag;
}

public void setFlag(boolean flag) {
this.flag = flag;
}

public Td(int id) {
this.id = id;
flag = true;
}

@Override
public void run() {
synchronized (this) {

while (!Thread.currentThread().isInterrupted()) {
try {
if (!flag) {
wait();
}
//sleep(3000);
// System.out.print(this.id);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}

}

#11


http://bbs.csdn.net/topics/390484059

#12


如果 就是想阻塞 然后唤醒指定的线程
#11楼的大哥 有给出不错的答案

#13


线程池呢.用.

#14


引用 10 楼 gmh0421 的回复:
终于能回复了
稍微做了下,不知道是否满足要求,一共两个类。因为电脑的问题,我指做了3个线程,10个就卡死了
package com.thread;

import java.util.*;
import java.util.Map.Entry;
import java.io.*;

public class TestThread {
HashMap<Integer, Td> hm;
String no;

public static void main(String[] args) {
TestThread tt = new TestThread();
while (true) {
tt.showMenu();

try {
BufferedReader strin = new BufferedReader(
new InputStreamReader(System.in));
tt.no = strin.readLine();
} catch (IOException e) {
e.printStackTrace();
}

switch (tt.no) {
case "1":
tt.showWaitThread(tt.hm);
System.out.println("请输入要选择的线程号:");
try {
BufferedReader strin = new BufferedReader(
new InputStreamReader(System.in));
tt.no = strin.readLine();
} catch (IOException e) {
e.printStackTrace();
}
tt.setWait(Integer.parseInt(tt.no));
break;
case "2":
tt.showWakeThread(tt.hm);
System.out.println("请输入要选择的线程号:");
try {
BufferedReader strin = new BufferedReader(
new InputStreamReader(System.in));
tt.no = strin.readLine();
} catch (IOException e) {
e.printStackTrace();
}
tt.setWake(Integer.parseInt(tt.no));
break;
case "3":
// 显示所有线程的情况
tt.showThread(tt.hm);
break;
case "4":
System.exit(0);

}
}
}

public TestThread() {
hm = new HashMap<Integer, Td>();
for (int n = 1; n <= 3; n++) {
Td t = new Td(n);
hm.put(n, t);
t.start();
}
}

public void showMenu() {
System.out.println("菜单");
System.out.println("1 阻塞线程");
System.out.println("2 唤醒线程");
System.out.println("3 显示线程情况");
System.out.println("4 退出");
System.out.println("请输入你要的选择:");
}

public void showThread(HashMap hm) {
Iterator a = hm.entrySet().iterator();
while (a.hasNext()) {
Entry t = (Entry) a.next();
System.out.println("第  " + t.getKey() + " 号线程的状态是: "
+ ((Td) t.getValue()).getState());
}
}

public void showWaitThread(HashMap hm) {
Iterator a = hm.entrySet().iterator();
while (a.hasNext()) {
Entry t = (Entry) a.next();
if (((Td) t.getValue()).getState().toString().equals("RUNNABLE")) {
System.out.println("第  " + t.getKey() + " 号线程的状态是: "
+ ((Td) t.getValue()).getState());
}
}
}

public void showWakeThread(HashMap hm) {
Iterator a = hm.entrySet().iterator();
while (a.hasNext()) {
Entry t = (Entry) a.next();
if (((Td) t.getValue()).getState().toString().equals("WAITING")) {
System.out.println("第  " + t.getKey() + " 号线程的状态是: "
+ ((Td) t.getValue()).getState());
}
}
}



public void setWait(int n) {

hm.get(n).setFlag(false);

}

public void setWake(int n) {
Td tmp = hm.get(n);
tmp.setFlag(true);
synchronized (tmp) {
tmp.notify();
}
}
}

package com.thread;

public class Td extends Thread {

int id;
boolean flag;

public boolean isFlag() {
return flag;
}

public void setFlag(boolean flag) {
this.flag = flag;
}

public Td(int id) {
this.id = id;
flag = true;
}

@Override
public void run() {
synchronized (this) {

while (!Thread.currentThread().isInterrupted()) {
try {
if (!flag) {
wait();
}
//sleep(3000);
// System.out.print(this.id);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}

}

Sorry,童鞋,暂时不能给你分,这个程序一跑,我的CPU占用率已经超过90%了。

#15


好吧,除了这点,能满足你的要求不?

#16


引用 15 楼 gmh0421 的回复:
好吧,除了这点,能满足你的要求不?

不行,太卡了;如果5个以上的话,基本上就要死机;你能否再想别的好办法?

#17


你想做什么....