Java 并发-条件同步方法
我正在一行一行地同时阅读两个文本文件 我特别想做的是,当每个线程上的Java 并发-条件同步方法,java,multithreading,Java,Multithreading,我正在一行一行地同时阅读两个文本文件 我特别想做的是,当每个线程上的lineCount相同时,我想查看扫描仪当前读取的字符串 我环顾四周,寻找我可以实现的某种模式,但我无法理解它将如何帮助我实现我的目标。我是并发编程新手 到目前为止,我所做的是使用counterSync方法同步字符串读取和打印,我知道我已经在那里执行了线程锁定/暂停操作,并查看了字符串 public class concurrencyTest { public static void main(String[] args) t
lineCount
相同时,我想查看扫描仪当前读取的字符串
我环顾四周,寻找我可以实现的某种模式,但我无法理解它将如何帮助我实现我的目标。我是并发编程新手
到目前为止,我所做的是使用counterSync
方法同步字符串读取和打印,我知道我已经在那里执行了线程锁定/暂停操作,并查看了字符串
public class concurrencyTest {
public static void main(String[] args) throws IOException {
String filePath1 = "path1.txt";
String filePath2 = "path2.txt";
reader reader = new reader();
MyThread source = new MyThread(reader, filePath1);
MyThread target = new MyThread(reader, filePath2);
source.start();
target.start();
}
static public class reader {
void read(String filePath) throws IOException {
readFile(filePath);
}
}
static synchronized void counterSync(String thread) {
System.out.println(thread);
}
static class MyThread extends Thread {
reader reader;
String filePath;
MyThread(reader reader, String filePath) {
this.reader = reader;
this.filePath = filePath;
}
@Override
public void run() {
try {
reader.read(filePath);
} catch (IOException e) {
e.printStackTrace();
}
}
}
static void readFile(String filePath) throws IOException {
FileInputStream inputStream = null;
Scanner sc = null;
int lineCount = 0;
try {
inputStream = new FileInputStream(filePath);
sc = new Scanner(inputStream, "UTF-8");
while (sc.hasNextLine()) {
lineCount++;
System.out.println(lineCount + "===" + sc.nextLine());
counterSync(sc.nextLine());
}
if (sc.ioException() != null) {
throw sc.ioException();
}
} finally {
if (inputStream != null) {
inputStream.close();
}
if (sc != null) {
sc.close();
}
}
}
}
似乎你没有发布一个完整的例子。但是,有几点一般性意见: 您可能可以对整数使用“比较和交换”逻辑,但不应期望它适用于更复杂的东西,如Java“字符串”或任何类型的容器 您只需使用语言中提供的同步对象即可。如果要更新甚至检查共享数据结构,必须持有正确的锁
当然,“线程安全队列”在许多设计中非常有用,因为它们促进了最常见的活动——消息传递——并允许各种线程以稍微不同的速度优雅地运行。您仍然需要锁定共享的任何内容,但尽管如此,这是一个非常有用的设计,与Unix®的“管道”一样古老。您似乎没有发布完整的示例。但是,有几点一般性意见: 您可能可以对整数使用“比较和交换”逻辑,但不应期望它适用于更复杂的东西,如Java“字符串”或任何类型的容器 您只需使用语言中提供的同步对象即可。如果要更新甚至检查共享数据结构,必须持有正确的锁
当然,“线程安全队列”在许多设计中非常有用,因为它们促进了最常见的活动——消息传递——并允许各种线程以稍微不同的速度优雅地运行。您仍然需要锁定共享的任何内容,但尽管如此,这是一种非常有用的设计,与Unix®的“管道”一样古老。好的,您需要的有点复杂,但仍然是可能的。
你的问题缺少一些例子,所以如果我在某些方面错了,请纠正我
您有两个线程:
- 螺纹1
- 螺纹2
和2个文件:
- 文件1
- 文件2
file1
file2
file3
file4
file5
file6
file7
file8
file9
文件2的内容:
file11
file22
file33
file44
file55
file66
file77
file88
file99
您希望停止相同行号上的所有线程,并对输出执行一些操作
这是读取文件的线程实现,我们将实例化它的2个实例,每个实例将管理一个文件
static class ReaderThread extends Thread {
private File fileToRead;
public final Object lock = new Object();
private String currentLine;
private AtomicInteger lineCount = new AtomicInteger(0);
public ReaderThread(File fileToRead) {
this.fileToRead = fileToRead;
}
@Override
public void run() {
synchronized (lock) {
try {
Stream<String> lines = Files.lines(Path.of(fileToRead.getPath()));
lines.forEach(line -> {
currentLine = line;
// Here's your logic on different lines
if (lineCount.get() == 4 || lineCount.get() == 5 || lineCount.get() == 6) {
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
lineCount.getAndIncrement();
});
} catch (IOException e) {
e.printStackTrace();
}
}
}
public String getCurrentLine() {
return currentLine;
}
public boolean isLocked() {
return getState().equals(State.WAITING);
}
}
执行该程序将产生以下输出:
以下是完整的进口清单:
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Stream;
请注意:这是一个粗鲁的例子,您需要正确地关闭线程进行管理,一些修饰符是公共的,所以要按照java指南封装它,正确地管理所有异常,并进行一些常规重构
如果您想要一个更通用的实现,以插入不同的线,以下应该是确定的:
static class HelperThread extends Thread {
private List<ReaderThread> threads;
@Override
public void run() {
while (true) {
if (threads.stream().allMatch(ReaderThread::isLocked)) {
System.out.println("next line:");
threads.forEach(thread -> {
synchronized (thread.lock) {
System.out.println(thread.getCurrentLine());
thread.lock.notify();
}
});
System.out.println("\n");
}
}
}
public HelperThread(List<ReaderThread> threads) {
this.threads = threads;
}
}
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Stream;
public class Main2 {
public static void main(String[] args) {
File f1 = new File(Objects.requireNonNull(Main2.class.getClassLoader().getResource("file1.txt")).getFile());
File f2 = new File(Objects.requireNonNull(Main2.class.getClassLoader().getResource("file2.txt")).getFile());
ReaderThread t1 = new ReaderThread(f1);
ReaderThread t2 = new ReaderThread(f2);
HelperThread helperThread = new HelperThread(List.of(t1, t2));
helperThread.start();
t1.setName("Reader1");
t1.setName("Reader2");
t1.start();
t2.start();
}
static class ReaderThread extends Thread {
private final File fileToRead;
private final Object lock = new Object();
private final AtomicInteger lineCount = new AtomicInteger(0);
private String currentLine;
public ReaderThread(File fileToRead) {
this.fileToRead = fileToRead;
}
@Override
public void run() {
synchronized (lock) {
try {
Stream<String> lines = Files.lines(Path.of(fileToRead.getPath()));
lines.forEach(line -> {
currentLine = line;
lineCount.getAndIncrement();
});
} catch (IOException e) {
e.printStackTrace();
}
}
}
public void lock() throws InterruptedException {
this.lock.wait();
}
public void unlock() {
this.lock.notify();
}
public boolean isLocked() {
return getState().equals(State.WAITING);
}
public Object getLock() {
return lock;
}
public AtomicInteger getLineCount() {
return lineCount;
}
public String getCurrentLine() {
return currentLine;
}
}
static class HelperThread extends Thread {
private List<ReaderThread> threads;
@Override
public void run() {
while (true) {
threads.forEach(t -> {
try {
if (t.getName().equals("Reader1") && t.getLineCount().get() == 3) t.lock();
if (t.getName().equals("Reader2") && t.getLineCount().get() == 4) t.lock();
} catch (InterruptedException e) {
e.printStackTrace();
}
});
if (threads.stream().allMatch(ReaderThread::isLocked)) {
System.out.println("next line:");
threads.forEach(t -> {
synchronized (t.getLock()) {
System.out.println(t.getCurrentLine());
t.unlock();
}
});
System.out.println("\n");
}
}
}
public HelperThread(List<ReaderThread> threads) {
this.threads = threads;
}
}
}
导入java.io.File;
导入java.io.IOException;
导入java.nio.file.Files;
导入java.nio.file.Path;
导入java.util.List;
导入java.util.Objects;
导入java.util.concurrent.AtomicInteger;
导入java.util.stream.stream;
公共类Main2{
公共静态void main(字符串[]args){
文件f1=新文件(Objects.requirennull(Main2.class.getClassLoader().getResource(“file1.txt”)).getFile());
文件f2=新文件(Objects.requirennull(Main2.class.getClassLoader().getResource(“file2.txt”)).getFile());
ReaderThread t1=新的ReaderThread(f1);
ReaderThread t2=新的ReaderThread(f2);
HelperThread HelperThread=新的HelperThread(List.of(t1,t2));
helperThread.start();
t1.设置名称(“读取器1”);
t1.设置名称(“读取器2”);
t1.start();
t2.start();
}
静态类ReaderThread扩展线程{
私有最终文件读取;
私有最终对象锁=新对象();
私有最终AtomicInteger lineCount=新的AtomicInteger(0);
专用字符串电流线;
公共读取器线程(文件或读取){
this.fileToRead=fileToRead;
}
@凌驾
公开募捐{
已同步(锁定){
试一试{
streamlines=Files.lines(Path.of(fileToRead.getPath());
行。forEach(行->{
currentLine=line;
lineCount.getAndIncrement();
});
}捕获(IOE异常){
e、 printStackTrace();
}
}
}
public void lock()引发InterruptedException{
这个。lock。wait();
}
公开作废解锁(){
this.lock.notify();
}
公共布尔值isLocked(){
返回getState().equals(State.WAITING);
}
公共对象getLock(){
返回锁;
}
公共原子整数getLineCount(){
返回行计数;
}
公共字符串getCurrentLine(){
回流线;
}
}
静态类HelperThread扩展线程{
私有列表线程;
@凌驾
公开募捐{
while(true){
threads.forEach(t->{
试一试{
如果(t.getName().equals(“Reader1”)和&t.getLineCount().get()==3)t.lock();
if(t.getName().eq
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Stream;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Stream;
public class Main2 {
public static void main(String[] args) {
File f1 = new File(Objects.requireNonNull(Main2.class.getClassLoader().getResource("file1.txt")).getFile());
File f2 = new File(Objects.requireNonNull(Main2.class.getClassLoader().getResource("file2.txt")).getFile());
ReaderThread t1 = new ReaderThread(f1);
ReaderThread t2 = new ReaderThread(f2);
HelperThread helperThread = new HelperThread(List.of(t1, t2));
helperThread.start();
t1.setName("Reader1");
t1.setName("Reader2");
t1.start();
t2.start();
}
static class ReaderThread extends Thread {
private final File fileToRead;
private final Object lock = new Object();
private final AtomicInteger lineCount = new AtomicInteger(0);
private String currentLine;
public ReaderThread(File fileToRead) {
this.fileToRead = fileToRead;
}
@Override
public void run() {
synchronized (lock) {
try {
Stream<String> lines = Files.lines(Path.of(fileToRead.getPath()));
lines.forEach(line -> {
currentLine = line;
lineCount.getAndIncrement();
});
} catch (IOException e) {
e.printStackTrace();
}
}
}
public void lock() throws InterruptedException {
this.lock.wait();
}
public void unlock() {
this.lock.notify();
}
public boolean isLocked() {
return getState().equals(State.WAITING);
}
public Object getLock() {
return lock;
}
public AtomicInteger getLineCount() {
return lineCount;
}
public String getCurrentLine() {
return currentLine;
}
}
static class HelperThread extends Thread {
private List<ReaderThread> threads;
@Override
public void run() {
while (true) {
threads.forEach(t -> {
try {
if (t.getName().equals("Reader1") && t.getLineCount().get() == 3) t.lock();
if (t.getName().equals("Reader2") && t.getLineCount().get() == 4) t.lock();
} catch (InterruptedException e) {
e.printStackTrace();
}
});
if (threads.stream().allMatch(ReaderThread::isLocked)) {
System.out.println("next line:");
threads.forEach(t -> {
synchronized (t.getLock()) {
System.out.println(t.getCurrentLine());
t.unlock();
}
});
System.out.println("\n");
}
}
}
public HelperThread(List<ReaderThread> threads) {
this.threads = threads;
}
}
}
public static void main(String[] args) throws IOException {
String filePath1 = "path1.txt";
String filePath2 = "path2.txt";
ReaderThread reader1 = new ReaderThread(filePath1);
ReaderThread reader2 = new ReaderThread(filePath2);
CyclicBarrier cyclicBarrier = new CyclicBarrier(2, () -> {
//processing when condition met in both thread
List<String> lines1 = reader1.getLines();
List<String> lines2 = reader2.getLines();
System.out.println(lines1.get(lines1.size() - 1) + " " + lines2.get(lines2.size()-1));
});
reader1.setCyclicBarrier(cyclicBarrier);
reader2.setCyclicBarrier(cyclicBarrier);
reader1.start();
reader2.start();
}
public static class ReaderThread extends Thread {
CyclicBarrier cyclicBarrier;
String file;
List<String> lines = new ArrayList<>();
public void setCyclicBarrier(CyclicBarrier cyclicBarrier) {
this.cyclicBarrier = cyclicBarrier;
}
public ReaderThread(String file) {
this.file = file;
}
@Override
public void run() {
try (BufferedReader reader = Files.newBufferedReader(Paths.get(file))) {
String line = null;
for (int i = 0; (line = reader.readLine()) != null; i++) {
lines.add(line);
//condition do something
if (i % 10 == 0) {
cyclicBarrier.await();
}
}
} catch (IOException | InterruptedException | BrokenBarrierException e) {
e.printStackTrace();
}
}
public List<String> getLines() {
return new ArrayList<>(lines);
}
}
this is from file1 1232123321312 this is from file 2 1232123321312
this is from file1 1232123321312 this is from file 2 1232123321312
this is from file1 1232123321312 this is from file 2 1232123321312