সম্পাদনা : এই ওয়াচ সার্ভিস পদ্ধতির ব্যবহারের পরিবর্তে, একটি সহজ 1 সেকেন্ডের টাইমার থ্রেডটি সূচকফিল.এক্সিজিস্ট () আছে কিনা তা পরীক্ষা করতে ব্যবহার করা যেতে পারে। এটি মুছুন, তারপরে অ্যাপ্লিকেশনটি ফ্রন্টে () এনে দিন।
সম্পাদনা : আমি জানতে চাই কেন এটিকে হ্রাস করা হয়েছিল। এটি আমি এখনও অবধি দেখেছি সেরা সমাধান। উদাহরণস্বরূপ, অন্য কোনও অ্যাপ্লিকেশনটি ইতিমধ্যে বন্দরে শোনার ক্ষেত্রে যদি সার্ভার সকেট পদ্ধতির ব্যর্থতা হয়।
মাইক্রোসফ্ট উইন্ডোজ সিসিনটার্নস টিসিপিভিউ (বা নেটস্যাট ব্যবহার করুন) ডাউনলোড করুন, এটি শুরু করুন, "স্টেট" অনুসারে বাছাই করুন, "তালিকাভুক্তি" বলছে এমন লাইন ব্লকটি সন্ধান করুন, যার দূরবর্তী ঠিকানাতে আপনার কম্পিউটারের নাম বলা হয়েছে, সেই পোর্টটি আপনার নতুন সকেটে রাখুন ()-সমাধান। আমার এটি প্রয়োগে আমি প্রতিবার ব্যর্থতা তৈরি করতে পারি। এবং এটি যৌক্তিক , কারণ এটি পদ্ধতির খুব ভিত্তি। বা আমি কীভাবে এটি বাস্তবায়ন করতে পারি না?
আমি এবং যদি আমি এই সম্পর্কে ভুল কিভাবে দয়া করে আমাকে জানান!
আমার দৃষ্টিভঙ্গি - যা আমি আপনাকে সম্ভব হলে তা অস্বীকার করতে বলছি - এটি হ'ল ডেভেলপারদের প্রোডাকশন কোডে এমন একটি পদ্ধতির ব্যবহার করার পরামর্শ দেওয়া হচ্ছে যা প্রায় 60000 ক্ষেত্রে কমপক্ষে 1 এ ব্যর্থ হবে। এবং যদি এই মতামতটি সঠিক বলে মনে হয়, তবে এটি সম্পূর্ণরূপে হতে পারে না যে কোনও সমাধান উপস্থাপিত হয় যা এই সমস্যাটি না করে এটি কোডের পরিমাণের জন্য সমালোচিত এবং সমালোচিত হয়।
তুলনায় সকেট পদ্ধতির অসুবিধা:
- যদি ভুল লটারির টিকিট (পোর্ট নম্বর) চয়ন করা হয় তবে ব্যর্থ হয়।
- একাধিক ব্যবহারকারীর পরিবেশে ব্যর্থ: একই সময়ে কেবলমাত্র একজন ব্যবহারকারী অ্যাপ্লিকেশনটি চালাতে পারেন। (ব্যবহারকারীর গাছে ফাইল (গুলি) তৈরি করতে আমার দৃষ্টিভঙ্গিটি কিছুটা পরিবর্তন করতে হবে, তবে এটি তুচ্ছ)
- ফায়ারওয়াল বিধি খুব কঠোর হলে ব্যর্থ হয়।
- সন্দেহজনক ব্যবহারকারীকে (যা আমি বন্যের সাথে দেখা করেছিলাম) বিস্মিত করে তোলে যখন আপনার পাঠ্য সম্পাদক কোনও সার্ভার সকেট দাবি করছেন তখন আপনি কী শেননিগানকে নিয়ে যাবেন wonder
আমি নতুন সিস্টেম-থেকে-বিদ্যমান-উদাহরণ জাভা যোগাযোগ সমস্যা এমনভাবে সমাধান করতে পারি যাতে প্রতিটি সিস্টেমে কাজ করা উচিত I সুতরাং, আমি প্রায় দুই ঘন্টা এই ক্লাস বেত্রাঘাত। কবজির মতো কাজ করে: ডি
এটি রবার্টের ফাইল লক পদ্ধতির (এই পৃষ্ঠায়ও) ভিত্তিক , যা আমি তখন থেকেই ব্যবহার করে আসছি। ইতিমধ্যে চলমান উদাহরণটি বলার জন্য যে অন্য একটি উদাহরণ শুরু করার চেষ্টা করেছিল (তবে তা হয়নি) ... একটি ফাইল তৈরি এবং তত্ক্ষণাত মোছা হয়েছে, এবং প্রথম উদাহরণটি এই ফোল্ডারটির সামগ্রীর পরিবর্তন সনাক্ত করতে ওয়াচ সার্ভিস ব্যবহার করে। আমি বিশ্বাস করতে পারি না যে সমস্যাটি কতটা মৌলিক তা বিবেচনা করে দৃশ্যত এটি একটি নতুন ধারণা।
এটি সহজেই ফাইলটি তৈরি এবং মুছে ফেলার জন্য সহজেই পরিবর্তন করা যেতে পারে এবং তারপরে তথ্য যুক্ত করা যেতে পারে যা যথাযথ উদাহরণটি মূল্যায়ন করতে পারে, উদাহরণস্বরূপ কমান্ড লাইন আর্গুমেন্টগুলি - এবং যথাযথ উদাহরণটি মুছে ফেলতে পারে। ব্যক্তিগতভাবে, আমার অ্যাপ্লিকেশনটির উইন্ডোটি কখন পুনরুদ্ধার করতে হবে এবং এটিকে সামনে পাঠানো উচিত তা কেবল আমার জানা দরকার।
উদাহরণ ব্যবহার:
public static void main(final String[] args) {
if (!SingleInstanceChecker.INSTANCE.isOnlyInstance(Main::otherInstanceTriedToLaunch, false)) {
System.exit(0);
}
System.out.println("Application starts properly because it's the only instance.");
}
private static void otherInstanceTriedToLaunch() {
System.err.println("Deiconified because other instance tried to start.");
}
এখানে ক্লাস:
package yourpackagehere;
import javax.swing.*;
import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.channels.FileLock;
import java.nio.file.*;
public enum SingleInstanceChecker {
INSTANCE;
final public static int POLLINTERVAL = 1000;
final public static File LOCKFILE = new File("SINGLE_INSTANCE_LOCKFILE");
final public static File DETECTFILE = new File("EXTRA_INSTANCE_DETECTFILE");
private boolean hasBeenUsedAlready = false;
private WatchService watchService = null;
private RandomAccessFile randomAccessFileForLock = null;
private FileLock fileLock = null;
public boolean isOnlyInstance(final Runnable codeToRunIfOtherInstanceTriesToStart, final boolean executeOnAWTEventDispatchThread) {
if (hasBeenUsedAlready) {
throw new IllegalStateException("This class/method can only be used once, which kinda makes sense if you think about it.");
}
hasBeenUsedAlready = true;
final boolean ret = canLockFileBeCreatedAndLocked();
if (codeToRunIfOtherInstanceTriesToStart != null) {
if (ret) {
installOtherInstanceLaunchAttemptWatcher(codeToRunIfOtherInstanceTriesToStart, executeOnAWTEventDispatchThread);
} else {
createAndDeleteOtherInstanceWatcherTriggerFile();
}
}
optionallyInstallShutdownHookThatCleansEverythingUp();
return ret;
}
private void createAndDeleteOtherInstanceWatcherTriggerFile() {
try {
final RandomAccessFile randomAccessFileForDetection = new RandomAccessFile(DETECTFILE, "rw");
randomAccessFileForDetection.close();
Files.deleteIfExists(DETECTFILE.toPath());
} catch (Exception e) {
e.printStackTrace();
}
}
private boolean canLockFileBeCreatedAndLocked() {
try {
randomAccessFileForLock = new RandomAccessFile(LOCKFILE, "rw");
fileLock = randomAccessFileForLock.getChannel().tryLock();
return fileLock != null;
} catch (Exception e) {
return false;
}
}
private void installOtherInstanceLaunchAttemptWatcher(final Runnable codeToRunIfOtherInstanceTriesToStart, final boolean executeOnAWTEventDispatchThread) {
try {
watchService = FileSystems.getDefault().newWatchService();
} catch (IOException e) {
e.printStackTrace();
return;
}
final File appFolder = new File("").getAbsoluteFile();
final Path appFolderWatchable = appFolder.toPath();
try {
appFolderWatchable.register(watchService, StandardWatchEventKinds.ENTRY_DELETE);
} catch (IOException e) {
e.printStackTrace();
return;
}
final Thread t = new Thread(() -> watchForDirectoryChangesOnExtraThread(codeToRunIfOtherInstanceTriesToStart, executeOnAWTEventDispatchThread));
t.setDaemon(true);
t.setName("directory content change watcher");
t.start();
}
private void optionallyInstallShutdownHookThatCleansEverythingUp() {
if (fileLock == null && randomAccessFileForLock == null && watchService == null) {
return;
}
final Thread shutdownHookThread = new Thread(() -> {
try {
if (fileLock != null) {
fileLock.release();
}
if (randomAccessFileForLock != null) {
randomAccessFileForLock.close();
}
Files.deleteIfExists(LOCKFILE.toPath());
} catch (Exception ignore) {
}
if (watchService != null) {
try {
watchService.close();
} catch (IOException e) {
e.printStackTrace();
}
}
});
Runtime.getRuntime().addShutdownHook(shutdownHookThread);
}
private void watchForDirectoryChangesOnExtraThread(final Runnable codeToRunIfOtherInstanceTriesToStart, final boolean executeOnAWTEventDispatchThread) {
while (true) {
try {
Thread.sleep(POLLINTERVAL);
} catch (InterruptedException e) {
e.printStackTrace();
}
final WatchKey wk;
try {
wk = watchService.poll();
} catch (ClosedWatchServiceException e) {
e.printStackTrace();
return;
}
if (wk == null || !wk.isValid()) {
continue;
}
for (WatchEvent<?> we : wk.pollEvents()) {
final WatchEvent.Kind<?> kind = we.kind();
if (kind == StandardWatchEventKinds.OVERFLOW) {
System.err.println("OVERFLOW of directory change events!");
continue;
}
final WatchEvent<Path> watchEvent = (WatchEvent<Path>) we;
final File file = watchEvent.context().toFile();
if (file.equals(DETECTFILE)) {
if (!executeOnAWTEventDispatchThread || SwingUtilities.isEventDispatchThread()) {
codeToRunIfOtherInstanceTriesToStart.run();
} else {
SwingUtilities.invokeLater(codeToRunIfOtherInstanceTriesToStart);
}
break;
} else {
System.err.println("THIS IS THE FILE THAT WAS DELETED: " + file);
}
}
wk.reset();
}
}
}