একক উদাহরণ জাভা অ্যাপ্লিকেশন কিভাবে প্রয়োগ করবেন?


89

একসময় আমি অনেকগুলি অ্যাপ্লিকেশন দেখতে পাই যেমন এমএসএন, উইন্ডোজ মিডিয়া প্লেয়ার ইত্যাদি যা একক দৃষ্টান্তের অ্যাপ্লিকেশন (যখন অ্যাপ্লিকেশন কোনও নতুন অ্যাপ্লিকেশন চলমান থাকাকালীন কার্যকর হয় তখন তৈরি হবে না)।

সি # তে, আমি এর জন্য Mutexক্লাস ব্যবহার করি তবে জাভাতে এটি কীভাবে করা যায় তা আমি জানি না।


জাভা Nio সঙ্গে একটি খুব সহজ পদ্ধতির সম্পূর্ণ উদাহরণ দেখতে stackoverflow.com/a/20015771/185022
AZ_

উত্তর:


62

আমি যদি এই নিবন্ধটি বিশ্বাস করি তবে :

লোকালহোস্ট ইন্টারফেসে একটি শ্রোতা সকেট খোলার প্রথম উদাহরণ থাকা। যদি এটি সকেটটি খুলতে সক্ষম হয় তবে অনুমান করা হয় যে এটি অ্যাপ্লিকেশনটির প্রথম উদাহরণ। যদি তা না হয় তবে অনুমান করা যায় যে এই অ্যাপ্লিকেশনটির একটি উদাহরণ ইতিমধ্যে চলছে। নতুন উদাহরণটি অবশ্যই বিদ্যমান উদাহরণটিকে অবহিত করতে হবে যে একটি প্রবর্তন করার চেষ্টা করা হয়েছিল, তারপরে প্রস্থান করুন। বিদ্যমান উদাহরণটি বিজ্ঞপ্তিটি পাওয়ার পরে গ্রহণ করে এবং শ্রোতাদের কাছে এমন একটি ইভেন্ট ছড়িয়ে দেয় যা ক্রিয়া পরিচালনা করে।

নোট: Ahe এ মন্তব্য ব্যবহার উল্লেখ করেছে InetAddress.getLocalHost()চতুর হতে পারে:

  • এটি ডিএইচসিপি-পরিবেশে প্রত্যাশার মতো কাজ করে না কারণ কম্পিউটারে নেটওয়ার্ক অ্যাক্সেস রয়েছে কিনা তার উপরে ঠিকানাটি নির্ভর করে returned
    সমাধানটি ছিল এর সাথে সংযোগ খুলতে InetAddress.getByAddress(new byte[] {127, 0, 0, 1});
    সম্ভবত এর সাথে সম্পর্কিত বাগ 4435662
  • আমি 4665037 ত্রুটিটিও পেয়েছি যা প্রত্যাশিত ফলাফলের চেয়ে বেশি রিপোর্ট করেছে getLocalHost: মেশিনের আইপি ঠিকানা, বনাম আসল ফলাফল: রিটার্ন 127.0.0.1

লিনাক্সে getLocalHostফিরতে অবাক 127.0.0.1হলেও উইন্ডোতে নয়।


অথবা আপনি ManagementFactoryঅবজেক্ট ব্যবহার করতে পারেন । যেমন এখানে ব্যাখ্যা করা হয়েছে :

getMonitoredVMs(int processPid)পদ্ধতি বর্তমান অ্যাপ্লিকেশনের PID, প্যারামিটার হিসাবে পায় এবং আবেদন নাম কম্যান্ড লাইন থেকে বলা হয়, উদাহরণস্বরূপ, অ্যাপ্লিকেশন শুরু হয়েছিল থেকে ধরা c:\java\app\test.jarপাথ, তারপর মান পরিবর্তনশীল " c:\\java\\app\\test.jar"। এইভাবে, আমরা নীচের কোডটির 17 লাইনটিতে কেবল অ্যাপ্লিকেশন নামটি ধরব।
এর পরে, আমরা একই নামের সাথে অন্য প্রক্রিয়াটির জন্য জেভিএম অনুসন্ধান করি, যদি আমরা এটি পাই এবং অ্যাপ্লিকেশন পিআইডি আলাদা হয় তবে এর অর্থ এটি দ্বিতীয় অ্যাপ্লিকেশন উদাহরণ।

জেএনএলপি এছাড়াও একটি অফার SingleInstanceListener


4
জেনে রাখুন যে মুষ্টি সমাধানটিতে একটি ত্রুটি রয়েছে। আমরা সম্প্রতি আবিষ্কার করেছি যে InetAddress.getLocalHost()ডিএইচসিপি-পরিবেশে প্রত্যাশার মতো কাজ করে না কারণ কম্পিউটারে নেটওয়ার্ক অ্যাক্সেস রয়েছে কিনা তার উপরে ঠিকানাটি নির্ভর করে depends সমাধানটির সাথে সংযোগ খুলতে হয়েছিল InetAddress.getByAddress(new byte[] {127, 0, 0, 1});
এহে

4
@ তিনি: দুর্দান্ত পয়েন্ট আমি আমার সম্পাদিত উত্তরে আপনার মন্তব্য পাশাপাশি ওরাকল-সান বাগ রিপোর্টের উল্লেখগুলিও অন্তর্ভুক্ত করেছি।
ভনসি

4
জাভাডক অনুসারে InetAddress.getByName(null)লুপ ব্যাক ইন্টারফেসের ঠিকানা প্রদান করে। আমি অনুমান করি এটি 127.0.0.1 ম্যানুয়ালি উল্লেখ করার পরে আরও ভাল theory
কায়াহর


4
@ পিউস শিওর, কোনও সমস্যা নেই: আমি এই লিঙ্কগুলি পুনরুদ্ধার করেছি।
ভোনসি

65

আমি মূল পদ্ধতিতে নিম্নলিখিত পদ্ধতিটি ব্যবহার করি। এটি আমি সবচেয়ে সহজ, সবচেয়ে শক্তিশালী এবং অন্তত অন্তর্নিহিত পদ্ধতিটি দেখেছি তাই আমি ভেবেছিলাম যে আমি এটি ভাগ করে নিই।

private static boolean lockInstance(final String lockFile) {
    try {
        final File file = new File(lockFile);
        final RandomAccessFile randomAccessFile = new RandomAccessFile(file, "rw");
        final FileLock fileLock = randomAccessFile.getChannel().tryLock();
        if (fileLock != null) {
            Runtime.getRuntime().addShutdownHook(new Thread() {
                public void run() {
                    try {
                        fileLock.release();
                        randomAccessFile.close();
                        file.delete();
                    } catch (Exception e) {
                        log.error("Unable to remove lock file: " + lockFile, e);
                    }
                }
            });
            return true;
        }
    } catch (Exception e) {
        log.error("Unable to create and/or lock file: " + lockFile, e);
    }
    return false;
}

ডেস্কটপ অ্যাপ্লিকেশনটির জন্য "লকফায়াল" পরামিতিটি কী হওয়া উচিত? অ্যাপ্লিকেশন জারের ফাইলের নাম? কিভাবে কিছু জার ফাইল নেই কিছু ক্লাস ফাইল?
5YrsLaterDBA 14

4
ম্যানুয়ালি ফাইল লকটি প্রকাশ করা এবং শাটডাউনে ফাইলটি বন্ধ করা কি সত্যিই প্রয়োজনীয়? প্রক্রিয়াটি মারা যাওয়ার পরে এটি কি স্বয়ংক্রিয়ভাবে ঘটে না?
ন্যাটিক্স

4
তবে বিদ্যুৎ মারা গেলে এবং শাটডাউন হুক না চালিয়ে কম্পিউটার বন্ধ হয়ে গেলে কী ঘটে? ফাইলটি অবিরত থাকবে এবং অ্যাপ্লিকেশনটি অপরিবর্তনীয়।
পেটর হুডেক

7
@ পেটারহুডেক এটি ঠিক আছে। অ্যাপ্লিকেশনটি কীভাবে শেষ হয়, ফাইল লকটি প্রকাশ করা হবে। যদি এটি যথাযথ শাটডাউন না হয়, তবে এটির পরবর্তী সময়ে অ্যাপ্লিকেশনটিকে এটি উপলব্ধি করার অনুমতি দেওয়ার সুবিধাও রয়েছে। যে কোনও ক্ষেত্রে: লকটি যা গণনা করে তা ফাইলের উপস্থিতি নয়। যদি ফাইলটি এখনও থাকে তবে অ্যাপ্লিকেশনটি যেভাবেই চালু হবে।
ড্রিমস্পেসের রাষ্ট্রপতি

@ রবার্ট: আপনার সমাধানের জন্য ধন্যবাদ, আমি তখন থেকেই এটি ব্যবহার করে আসছি। এবং ঠিক এখনই, আমি এটি ইতিমধ্যে বিদ্যমান উদাহরণের সাথে যোগাযোগ করার জন্য এটি আরও প্রসারিত করেছি যে অন্য উদাহরণ শুরু করার চেষ্টা করেছিল - ওয়াচ সার্ভিস ফোল্ডারটি ব্যবহার করে! stackoverflow.com/a/36772436/3500521
ড্রিমস্পেসের সভাপতি

10

যদি অ্যাপ হয়। একটি জিইউআই রয়েছে, এটি জেডাব্লুএসের সাথে চালু করুন এবং এটি ব্যবহার করুন SingleInstanceService

হালনাগাদ

জাভা প্লাগ-ইন (অ্যাপলেট এবং জেডাব্লুএস অ্যাপ্লিকেশন উভয়ের জন্য প্রয়োজনীয়) ওরাকল দ্বারা হ্রাস করা হয়েছিল এবং জেডিকে থেকে সরানো হয়েছিল। ব্রাউজার নির্মাতারা এটি ইতিমধ্যে তাদের ব্রাউজারগুলি থেকে সরিয়ে ফেলেছে।

সুতরাং এই উত্তরটি বিচ্ছিন্ন। পুরানো ডকুমেন্টেশনের দিকে তাকিয়ে থাকা লোকদের সতর্ক করতে এখানে এটি রেখে দেওয়া।


4
এছাড়াও মনে রাখবেন যে এটি প্রদর্শিত হয়েছে যে চলমান উদাহরণটি নতুন উদাহরণ এবং তাদের যুক্তি সম্পর্কে জানানো যেতে পারে যাতে এই জাতীয় প্রোগ্রামে যোগাযোগ করা সহজ হয়।
থোরবজর্ন রাভন অ্যান্ডারসন

6

হ্যাঁ এটি নিগ্রহের জন্য আরসিপি গ্রহনের একক দৃষ্টান্তের আবেদনটির নীচে সত্যই একটি উত্তম উত্তর আমার কোড

in application.java

if(!isFileshipAlreadyRunning()){
        MessageDialog.openError(display.getActiveShell(), "Fileship already running", "Another instance of this application is already running.  Exiting.");
        return IApplication.EXIT_OK;
    } 


private static boolean isFileshipAlreadyRunning() {
    // socket concept is shown at http://www.rbgrn.net/content/43-java-single-application-instance
    // but this one is really great
    try {
        final File file = new File("FileshipReserved.txt");
        final RandomAccessFile randomAccessFile = new RandomAccessFile(file, "rw");
        final FileLock fileLock = randomAccessFile.getChannel().tryLock();
        if (fileLock != null) {
            Runtime.getRuntime().addShutdownHook(new Thread() {
                public void run() {
                    try {
                        fileLock.release();
                        randomAccessFile.close();
                        file.delete();
                    } catch (Exception e) {
                        //log.error("Unable to remove lock file: " + lockFile, e);
                    }
                }
            });
            return true;
        }
    } catch (Exception e) {
       // log.error("Unable to create and/or lock file: " + lockFile, e);
    }
    return false;
}

5

আমরা এর জন্য ফাইল লকিং ব্যবহার করি (ব্যবহারকারীর অ্যাপ্লিকেশন ডেটা ডিরেক্টরিতে একটি ম্যাজিক ফাইলে একটি এক্সক্লুসিভ লক ধরুন) তবে আমরা প্রাথমিকভাবে একাধিক ঘটনা চালিয়ে যাওয়া থেকে রোধ করতে আগ্রহী।

আপনি যদি প্রথম বারের মতো দ্বিতীয় বার কমান্ড লাইন আরোগুলি পাস করার চেষ্টা করছেন, তবে লোকালহোস্টে সকেট সংযোগ ব্যবহার করে একটি পাথর দিয়ে দুটি পাখি মারা যাবে। সাধারণ অ্যালগরিদম:

  • প্রবর্তনকালে, লোকালহোস্টে XXXX বন্দরে শ্রোতাদের খোলার চেষ্টা করুন
  • যদি ব্যর্থ হয় তবে লোকালহোস্টের সেই বন্দরে কোনও লেখককে খুলুন এবং কমান্ড লাইন আরগগুলি প্রেরণ করুন, তারপরে শাটডাউন করুন
  • অন্যথায় লোকালহোস্টে XXXXX বন্দরটিতে শুনুন। কমান্ড লাইন আরোগুলি গ্রহণ করার সময়, তাদের প্রসেস করুন যেন অ্যাপ্লিকেশনটি সেই কমান্ড লাইনের সাহায্যে চালু করা হয়েছিল।

5

আমি একটি সমাধান পেয়েছি, কিছুটা কার্টুনিশ ব্যাখ্যা, তবে এখনও বেশিরভাগ ক্ষেত্রেই কাজ করে। এটি স্টাফ তৈরি করতে প্লেইন পুরাতন লক ফাইলটি ব্যবহার করে তবে একেবারে ভিন্ন দৃষ্টিতে:

http://javalandcreen.blogspot.com/2008/07/single-instance-from-your-application.html

আমি মনে করি এটি কঠোর ফায়ারওয়াল সেটিং সহ তাদের সহায়তা করবে।


হ্যাঁ, এটি একটি ভাল উপায় হিসেবে লক ঘটনা প্রকাশ করা যাবে আবেদন ক্র্যাশ বা :) এর
কমিক্স্ পিত্ত Benoît

5

আপনি Junni লাইব্রেরি ব্যবহার করতে পারেন। এটি একক-উদাহরণ জাভা অ্যাপ্লিকেশন চালনার জন্য সহায়তা সরবরাহ করে এবং এটি ওপেন সোর্স।

http://www.sauronsoftware.it/projects/ জুনিক /

Junni গ্রন্থাগারটি একই সাথে জাভা অ্যাপ্লিকেশনটির আরও দৃষ্টান্তগুলি চালানোর জন্য কোনও ব্যবহারকারীকে আটকাতে ব্যবহার করা যেতে পারে।

JUnique একই ব্যবহারকারী দ্বারা চালু করা সমস্ত JVM দৃষ্টান্তের মধ্যে ভাগ করা লক এবং যোগাযোগ চ্যানেলগুলি প্রয়োগ করে।

public static void main(String[] args) {
    String appId = "myapplicationid";
    boolean alreadyRunning;
    try {
        JUnique.acquireLock(appId, new MessageHandler() {
            public String handle(String message) {
                // A brand new argument received! Handle it!
                return null;
            }
        });
        alreadyRunning = false;
    } catch (AlreadyLockedException e) {
        alreadyRunning = true;
    }
    if (!alreadyRunning) {
        // Start sequence here
    } else {
        for (int i = 0; i < args.length; i++) {
            JUnique.sendMessage(appId, args[0]));
        }
    }
}

হুডের অধীনে, এটি% USER_DATA% /। জুনিক ফোল্ডারে ফাইল লক তৈরি করে এবং প্রতিটি অনন্য অ্যাপ্লিকেশনের জন্য এলোমেলো বন্দরে একটি সার্ভার সকেট তৈরি করে যা জাভা অ্যাপ্লিকেশনগুলির মধ্যে বার্তা প্রেরণ / গ্রহণ করতে দেয়।


কোনও নেটওয়ার্কে জাভা অ্যাপ্লিকেশনটির বহু উদাহরণ রোধ করতে আমি কি এটি ব্যবহার করতে পারি? ওরফে, আমার অ্যাপ্লিকেশনটির কেবলমাত্র একটি উদাহরণ আমার পুরো নেটওয়ার্কের মধ্যে অনুমোদিত
ওয়ানার


2

ম্যানেজমেন্টফ্যাক্টরি ক্লাস J2SE 5.0 বা তার পরে বিশদে সমর্থিত supported

তবে এখন আমি জেএসইএস ১.৪ ব্যবহার করি এবং আমি এটি http://audiprimadhanty.wordpress.com/2008/06/30/ensuring-one-instance-of-application-running-at-one-time/ খুঁজে পেয়েছি তবে আমি কখনই পরীক্ষা করি না। আপনি এটি সম্পর্কে কি মনে করেন?


আমি বিশ্বাস করি যে এটি আমার উত্তরের প্রথম লিঙ্কে মূলত বর্ণিত হয়েছে ... rbgrn.net/blog/2008/05/ java
single

2

আপনি পছন্দগুলি API ব্যবহার করার চেষ্টা করতে পারেন। এটি প্ল্যাটফর্মটি স্বাধীন।


আমি এই ধারণাটি পছন্দ করি যেহেতু এপিআই সহজ তবে সম্ভবত কিছু ভাইরাস স্ক্যানার আপনাকে রেজিস্ট্রি পরিবর্তন করতে পছন্দ করবে না তাই আপনি সফ্টওয়্যার ফায়ারওয়াল সহ সিস্টেমে আরএমআই ব্যবহার করার মতো সমস্যা পেতে পারেন .... নিশ্চিত না।
Cal

@ ক্যাল তবে একই সমস্যা ফাইল পরিবর্তন / লকিং / ইত্যাদি নিয়ে ... আপনি কি ভাবেন না?
অ্যালেক্স

2

একক মেশিনে বা এমনকি পুরো একটি নেটওয়ার্কে উদাহরণের সংখ্যা সীমাবদ্ধ করার আরও সাধারণ উপায় হ'ল মাল্টিকাস্ট সকেট ব্যবহার করা।

একটি মাল্টিকাস্ট সকেট ব্যবহার করে, আপনাকে আপনার অ্যাপ্লিকেশনটির যে কোনও পরিমাণে বার্তায় সম্প্রচার করতে সক্ষম করে, যার কয়েকটি শারীরিকভাবে রিমোট মেশিনে কর্পোরেট নেটওয়ার্ক জুড়ে থাকতে পারে।

এই জাতীয় জিনিস নিয়ন্ত্রণ করতে আপনি বিভিন্ন ধরণের কনফিগারেশন সক্ষম করতে পারেন

  • এক বা একাধিক মেশিন প্রতি দৃষ্টান্ত
  • নেটওয়ার্ক প্রতি এক বা একাধিক উদাহরণ (যেমন ক্লায়েন্টের সাইটে ইনস্টলগুলি নিয়ন্ত্রণ করা)

জাভার মাল্টিকাস্ট সমর্থন মারফত java.net প্যাকেজ সঙ্গে MulticastSocket & DatagramSocket হচ্ছে প্রধান সরঞ্জাম।

দ্রষ্টব্য : মাল্টিকাস্টস্কট ডেটা প্যাকেট সরবরাহের গ্যারান্টি দেয় না, সুতরাং আপনার জেগ্রুপের মতো মাল্টিকাস্ট সকেটের উপরে নির্মিত একটি সরঞ্জাম ব্যবহার করা উচিত । JGroups করে সমস্ত ডেটা গ্যারান্টি ডেলিভারি। এটি একটি একক জার ফাইল, খুব সাধারণ এপিআই সহ।

জেগ্রুপগুলি প্রায় কিছুকাল হয়েছে, এবং শিল্পের কিছু চিত্তাকর্ষক ব্যবহার রয়েছে, উদাহরণস্বরূপ এটি জেবসের ক্লাস্টারিং মেকানিজমিকে ক্লাস্টারের সমস্ত ক্ষেত্রে ডেটা সম্প্রচার করে data

জেগ্রুপগুলি ব্যবহার করতে, কোনও অ্যাপ্লিকেশনটির উদাহরণ সীমাবদ্ধ করার জন্য (একটি মেশিন বা কোনও নেটওয়ার্কে, বলতে দিন: কোনও গ্রাহক যে পরিমাণ লাইসেন্স কিনেছেন) ধারণাটি খুব সহজ:

  • আপনার অ্যাপ্লিকেশন শুরু হওয়ার পরে, প্রতিটি উদাহরণ একটি নামী গোষ্ঠী যেমন "আমার গ্রেট অ্যাপ গ্রুপ" - এ যোগদানের চেষ্টা করে। 0, 1 বা এন সদস্যদের অনুমতি দেওয়ার জন্য আপনি এই গোষ্ঠীটি কনফিগার করেছেন
  • যখন আপনি এর জন্য কনফিগার করেছেন তার চেয়ে বেশি যখন গ্রুপের সদস্য গণনা হয় .. আপনার অ্যাপ্লিকেশনটি শুরু করতে অস্বীকার করা উচিত।

1

আপনি একটি মেমরি ম্যাপযুক্ত ফাইলটি খুলতে পারেন এবং তারপরে দেখুন যে ফাইলটি ইতিমধ্যে উন্মুক্ত রয়েছে। যদি এটি ইতিমধ্যে খোলা থাকে তবে আপনি মূল থেকে ফিরে আসতে পারেন।

অন্যান্য উপায় হ'ল লক ফাইল (স্ট্যান্ডার্ড ইউনিক্স অনুশীলন) ব্যবহার করা। আরও একটি উপায় হ'ল ক্লিপবোর্ডে কিছু ইতিমধ্যে রয়েছে কিনা তা খতিয়ে দেখার পরে যখন মূল শুরু হয় তখন ক্লিপবোর্ডে কিছু রাখা।

অন্যথায়, আপনি একটি শ্রবণ মোডে একটি সকেট খুলতে পারেন (সার্ভারসকেট)। প্রথমে hte সকেটে সংযোগ স্থাপনের চেষ্টা করুন; যদি আপনি সংযোগ করতে না পারেন তবে সার্ভারসকেট খুলুন। আপনি যদি সংযোগ স্থাপন করেন, তবে আপনি জানেন যে অন্য একটি উদাহরণ ইতিমধ্যে চলছে।

সুতরাং, কোনও অ্যাপ্লিকেশন চলছে কিনা তা জানার জন্য কোনও সিস্টেমের সংস্থান ব্যবহার করা যেতে পারে।

বিআর, ~ এ


এই আইডিয়াগুলির জন্য আপনার কি কোড আছে? এছাড়াও, যদি আমি চাই যে যদি ব্যবহারকারী কোনও নতুন উদাহরণ শুরু করে, এটি পূর্ববর্তী সমস্তগুলি বন্ধ করে দেবে?
অ্যান্ড্রয়েড বিকাশকারী

1

আমি তার জন্য সকেট ব্যবহার করেছি এবং নির্ভর করে যদি অ্যাপ্লিকেশনটি ক্লায়েন্টের পাশে বা সার্ভারের দিকে থাকে তবে আচরণটি কিছুটা আলাদা:

  • ক্লায়েন্ট পক্ষ: যদি ইতিমধ্যে একটি দৃষ্টান্ত উপস্থিত থাকে (আমি একটি নির্দিষ্ট পোর্টে শুনতে পারি না) আমি অ্যাপ্লিকেশন প্যারামিটারগুলি পাস করব এবং প্রস্থান করব (আপনি পূর্ববর্তী উদাহরণে কিছু ক্রিয়া সম্পাদন করতে চাইতে পারেন) যদি না আমি অ্যাপ্লিকেশনটি শুরু করব।
  • সার্ভারের দিক: যদি ইতিমধ্যে কোনও উদাহরণ উপস্থিত থাকে তবে আমি একটি বার্তা মুদ্রণ করব এবং প্রস্থান করব, না হলে আমি অ্যাপ্লিকেশনটি শুরু করব।

1
পাবলিক ক্লাস সিঙ্গলআইন্সট্যান্স {
    পাবলিক স্ট্যাটিক ফাইনাল স্ট্রিং LOCK = System.getProperty ("user.home") + File.separator + "টেস্ট.লক";
    পাবলিক স্ট্যাটিক ফাইনাল স্ট্রিং পিআইপিই = System.getProperty ("user.home") + File.separator + "টেস্ট.পাইপ";
    প্রাইভেট স্ট্যাটিক JFrame ফ্রেম = নাল;

    পাবলিক স্ট্যাটিক অকার্যকর প্রধান (স্ট্রিং [] আরগস) {
        চেষ্টা করুন
            ফাইলচ্যানেল লকচ্যানেল = নতুন র‌্যান্ডমএ্যাক্সেসফিল ​​(লক, "আরডব্লু")। getChannel ();
            ফাইললক ফ্লক = নাল; 
            চেষ্টা করুন
                flk = লকচ্যানেল.ট্রি লক ();
            } ধরা (নিক্ষেপযোগ্য টি) {
                t.printStackTrace ();
            }
            if (flk == নাল ||! flk.isValid ()) {
                System.out.println ("চালিয়ে যাওয়া, পাইপে একটি বার্তা রেখে প্রস্থান করা ...");
                ফাইলচ্যানেল পাইপ চ্যানেল = নাল;
                চেষ্টা করুন
                    পাইপ চ্যানেল = নতুন র‌্যান্ডমএকসেসফাইল (পিআইপিই, "আরডাব্লু")। getChannel ();
                    ম্যাপডবাইটবফার বিবি = পাইপচ্যানেল.ম্যাপ (ফাইলচ্যানেল.ম্যাপমোড.আআআআআআডি_আরআইটি, 0, 1);
                    বিবি.পুট (0, (বাইট) 1);
                    বিবি.ফোর্স ();
                } ধরা (নিক্ষেপযোগ্য টি) {
                    t.printStackTrace ();
                অবশেষে {
                    যদি (পাইপচ্যানেল! = নাল) {
                        চেষ্টা করুন
                            পাইপচ্যানেল.ক্লোজ ();
                        } ধরা (নিক্ষেপযোগ্য টি) {
                            t.printStackTrace ();
                        }
                    } 
                }
                System.exit (0);
            }
            // আমরা লকটি প্রকাশ করি না এবং এখানে চ্যানেলটি বন্ধ করি না, 
            // অ্যাপ্লিকেশন ক্র্যাশ হওয়ার পরে বা সাধারণত বন্ধ হয়ে যাওয়ার পরে এটি করা হবে। 
            সুইং ইউটিলিটি.ইনওকলেটার (
                নতুন চলমান () {
                    সর্বজনীন শূন্য রান () {
                        createAndShowGUI ();
                    }
                }
            );

            ফাইলচ্যানেল পাইপ চ্যানেল = নাল;
            চেষ্টা করুন
                পাইপ চ্যানেল = নতুন র‌্যান্ডমএকসেসফাইল (পিআইপিই, "আরডাব্লু")। getChannel ();
                ম্যাপডবাইটবফার বিবি = পাইপচ্যানেল.ম্যাপ (ফাইলচ্যানেল.ম্যাপমোড.আআআআআআডি_আরআইটি, 0, 1);
                (সত্য) while
                    বাইট খ = bb.get (0);
                    যদি (b> 0)
                        বিবি.পুট (0, (বাইট) 0);
                        বিবি.ফোর্স ();
                        সুইং ইউটিলিটি.ইনওকলেটার (
                            নতুন চলমান () {
                                সর্বজনীন শূন্য রান () {
                                    ফ্রেম.সেটএক্সটেন্ডডস্টেট (জেফ্রেম.এনআরএমএল);
                                    ফ্রেম.সেটএলওয়েসঅনটপ (সত্য);
                                    ফ্রেম.টোফ্রন্ট ();
                                    ফ্রেম.সেটএলওয়েসঅনটপ (মিথ্যা);
                                }
                            }
                        );
                    }
                    থ্রেড.স্লিপ (1000);
                }
            } ধরা (নিক্ষেপযোগ্য টি) {
                t.printStackTrace ();
            অবশেষে {
                যদি (পাইপচ্যানেল! = নাল) {
                    চেষ্টা করুন
                        পাইপচ্যানেল.ক্লোজ ();
                    } ধরা (নিক্ষেপযোগ্য টি) {
                        t.printStackTrace ();
                    } 
                } 
            }
        } ধরা (নিক্ষেপযোগ্য টি) {
            t.printStackTrace ();
        } 
    }

    সর্বজনীন স্ট্যাটিক শূন্য তৈরি এবং AndShowGUI () {

        ফ্রেম = নতুন জেফ্রেম ();
        ফ্রেম.সেট ডিফল্ট ক্লোস অফারেশন (JFrame.EXIT_ON_CLOSE);
        ফ্রেম.সেটসাইজ (800, 650);
        ফ্রেম.সেট কনটেন্টপেইন () যোগ করুন (নতুন জেবেল ("উইন্ডো মেইন"), 
                    সুইংকনস্ট্যান্টস.সেন্টার), বর্ডারআলআউট.সেন্টার);
        ফ্রেম.সেটলোকেশন রিলেটিভটো (নাল);
        ফ্রেম.সেটভিজিবল (সত্য);
    }
}


1

সম্পাদনা : এই ওয়াচ সার্ভিস পদ্ধতির ব্যবহারের পরিবর্তে, একটি সহজ 1 সেকেন্ডের টাইমার থ্রেডটি সূচকফিল.এক্সিজিস্ট () আছে কিনা তা পরীক্ষা করতে ব্যবহার করা যেতে পারে। এটি মুছুন, তারপরে অ্যাপ্লিকেশনটি ফ্রন্টে () এনে দিন।

সম্পাদনা : আমি জানতে চাই কেন এটিকে হ্রাস করা হয়েছিল। এটি আমি এখনও অবধি দেখেছি সেরা সমাধান। উদাহরণস্বরূপ, অন্য কোনও অ্যাপ্লিকেশনটি ইতিমধ্যে বন্দরে শোনার ক্ষেত্রে যদি সার্ভার সকেট পদ্ধতির ব্যর্থতা হয়।

মাইক্রোসফ্ট উইন্ডোজ সিসিনটার্নস টিসিপিভিউ (বা নেটস্যাট ব্যবহার করুন) ডাউনলোড করুন, এটি শুরু করুন, "স্টেট" অনুসারে বাছাই করুন, "তালিকাভুক্তি" বলছে এমন লাইন ব্লকটি সন্ধান করুন, যার দূরবর্তী ঠিকানাতে আপনার কম্পিউটারের নাম বলা হয়েছে, সেই পোর্টটি আপনার নতুন সকেটে রাখুন ()-সমাধান। আমার এটি প্রয়োগে আমি প্রতিবার ব্যর্থতা তৈরি করতে পারি। এবং এটি যৌক্তিক , কারণ এটি পদ্ধতির খুব ভিত্তি। বা আমি কীভাবে এটি বাস্তবায়ন করতে পারি না?

আমি এবং যদি আমি এই সম্পর্কে ভুল কিভাবে দয়া করে আমাকে জানান!

আমার দৃষ্টিভঙ্গি - যা আমি আপনাকে সম্ভব হলে তা অস্বীকার করতে বলছি - এটি হ'ল ডেভেলপারদের প্রোডাকশন কোডে এমন একটি পদ্ধতির ব্যবহার করার পরামর্শ দেওয়া হচ্ছে যা প্রায় 60000 ক্ষেত্রে কমপক্ষে 1 এ ব্যর্থ হবে। এবং যদি এই মতামতটি সঠিক বলে মনে হয়, তবে এটি সম্পূর্ণরূপে হতে পারে না যে কোনও সমাধান উপস্থাপিত হয় যা এই সমস্যাটি না করে এটি কোডের পরিমাণের জন্য সমালোচিত এবং সমালোচিত হয়।

তুলনায় সকেট পদ্ধতির অসুবিধা:

  • যদি ভুল লটারির টিকিট (পোর্ট নম্বর) চয়ন করা হয় তবে ব্যর্থ হয়।
  • একাধিক ব্যবহারকারীর পরিবেশে ব্যর্থ: একই সময়ে কেবলমাত্র একজন ব্যবহারকারী অ্যাপ্লিকেশনটি চালাতে পারেন। (ব্যবহারকারীর গাছে ফাইল (গুলি) তৈরি করতে আমার দৃষ্টিভঙ্গিটি কিছুটা পরিবর্তন করতে হবে, তবে এটি তুচ্ছ)
  • ফায়ারওয়াল বিধি খুব কঠোর হলে ব্যর্থ হয়।
  • সন্দেহজনক ব্যবহারকারীকে (যা আমি বন্যের সাথে দেখা করেছিলাম) বিস্মিত করে তোলে যখন আপনার পাঠ্য সম্পাদক কোনও সার্ভার সকেট দাবি করছেন তখন আপনি কী শেননিগানকে নিয়ে যাবেন wonder

আমি নতুন সিস্টেম-থেকে-বিদ্যমান-উদাহরণ জাভা যোগাযোগ সমস্যা এমনভাবে সমাধান করতে পারি যাতে প্রতিটি সিস্টেমে কাজ করা উচিত I সুতরাং, আমি প্রায় দুই ঘন্টা এই ক্লাস বেত্রাঘাত। কবজির মতো কাজ করে: ডি

এটি রবার্টের ফাইল লক পদ্ধতির (এই পৃষ্ঠায়ও) ভিত্তিক , যা আমি তখন থেকেই ব্যবহার করে আসছি। ইতিমধ্যে চলমান উদাহরণটি বলার জন্য যে অন্য একটি উদাহরণ শুরু করার চেষ্টা করেছিল (তবে তা হয়নি) ... একটি ফাইল তৈরি এবং তত্ক্ষণাত মোছা হয়েছে, এবং প্রথম উদাহরণটি এই ফোল্ডারটির সামগ্রীর পরিবর্তন সনাক্ত করতে ওয়াচ সার্ভিস ব্যবহার করে। আমি বিশ্বাস করতে পারি না যে সমস্যাটি কতটা মৌলিক তা বিবেচনা করে দৃশ্যত এটি একটি নতুন ধারণা।

এটি সহজেই ফাইলটি তৈরি এবং মুছে ফেলার জন্য সহজেই পরিবর্তন করা যেতে পারে এবং তারপরে তথ্য যুক্ত করা যেতে পারে যা যথাযথ উদাহরণটি মূল্যায়ন করতে পারে, উদাহরণস্বরূপ কমান্ড লাইন আর্গুমেন্টগুলি - এবং যথাযথ উদাহরণটি মুছে ফেলতে পারে। ব্যক্তিগতভাবে, আমার অ্যাপ্লিকেশনটির উইন্ডোটি কখন পুনরুদ্ধার করতে হবে এবং এটিকে সামনে পাঠানো উচিত তা কেবল আমার জানা দরকার।

উদাহরণ ব্যবহার:

public static void main(final String[] args) {

    // ENSURE SINGLE INSTANCE
    if (!SingleInstanceChecker.INSTANCE.isOnlyInstance(Main::otherInstanceTriedToLaunch, false)) {
        System.exit(0);
    }

    // launch rest of application here
    System.out.println("Application starts properly because it's the only instance.");
}

private static void otherInstanceTriedToLaunch() {
    // Restore your application window and bring it to front.
    // But make sure your situation is apt: This method could be called at *any* time.
    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.*;




/**
 * SingleInstanceChecker v[(2), 2016-04-22 08:00 UTC] by dreamspace-president.com
 * <p>
 * (file lock single instance solution by Robert https://stackoverflow.com/a/2002948/3500521)
 */
public enum SingleInstanceChecker {

    INSTANCE; // HAHA! The CONFUSION!


    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;


    /**
     * CAN ONLY BE CALLED ONCE.
     * <p>
     * Assumes that the program will close if FALSE is returned: The other-instance-tries-to-launch listener is not
     * installed in that case.
     * <p>
     * Checks if another instance is already running (temp file lock / shutdownhook). Depending on the accessibility of
     * the temp file the return value will be true or false. This approach even works even if the virtual machine
     * process gets killed. On the next run, the program can even detect if it has shut down irregularly, because then
     * the file will still exist. (Thanks to Robert https://stackoverflow.com/a/2002948/3500521 for that solution!)
     * <p>
     * Additionally, the method checks if another instance tries to start. In a crappy way, because as awesome as Java
     * is, it lacks some fundamental features. Don't worry, it has only been 25 years, it'll sure come eventually.
     *
     * @param codeToRunIfOtherInstanceTriesToStart Can be null. If not null and another instance tries to start (which
     *                                             changes the detect-file), the code will be executed. Could be used to
     *                                             bring the current (=old=only) instance to front. If null, then the
     *                                             watcher will not be installed at all, nor will the trigger file be
     *                                             created. (Null means that you just don't want to make use of this
     *                                             half of the class' purpose, but then you would be better advised to
     *                                             just use the 24 line method by Robert.)
     *                                             <p>
     *                                             BE CAREFUL with the code: It will potentially be called until the
     *                                             very last moment of the program's existence, so if you e.g. have a
     *                                             shutdown procedure or a window that would be brought to front, check
     *                                             if the procedure has not been triggered yet or if the window still
     *                                             exists / hasn't been disposed of yet. Or edit this class to be more
     *                                             comfortable. This would e.g. allow you to remove some crappy
     *                                             comments. Attribution would be nice, though.
     * @param executeOnAWTEventDispatchThread      Convenience function. If false, the code will just be executed. If
     *                                             true, it will be detected if we're currently on that thread. If so,
     *                                             the code will just be executed. If not so, the code will be run via
     *                                             SwingUtilities.invokeLater().
     * @return if this is the only instance
     */
    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) {
                // Only if this is the only instance, it makes sense to install a watcher for additional instances.
                installOtherInstanceLaunchAttemptWatcher(codeToRunIfOtherInstanceTriesToStart, executeOnAWTEventDispatchThread);
            } else {
                // Only if this is NOT the only instance, it makes sense to create&delete the trigger file that will effect notification of the other instance.
                //
                // Regarding "codeToRunIfOtherInstanceTriesToStart != null":
                // While creation/deletion of the file concerns THE OTHER instance of the program,
                // making it dependent on the call made in THIS instance makes sense
                // because the code executed is probably the same.
                createAndDeleteOtherInstanceWatcherTriggerFile();
            }
        }

        optionallyInstallShutdownHookThatCleansEverythingUp();

        return ret;
    }


    private void createAndDeleteOtherInstanceWatcherTriggerFile() {

        try {
            final RandomAccessFile randomAccessFileForDetection = new RandomAccessFile(DETECTFILE, "rw");
            randomAccessFileForDetection.close();
            Files.deleteIfExists(DETECTFILE.toPath()); // File is created and then instantly deleted. Not a problem for the WatchService :)
        } 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) {

        // PREPARE WATCHSERVICE AND STUFF
        try {
            watchService = FileSystems.getDefault().newWatchService();
        } catch (IOException e) {
            e.printStackTrace();
            return;
        }
        final File appFolder = new File("").getAbsoluteFile(); // points to current folder
        final Path appFolderWatchable = appFolder.toPath();


        // REGISTER CURRENT FOLDER FOR WATCHING FOR FILE DELETIONS
        try {
            appFolderWatchable.register(watchService, StandardWatchEventKinds.ENTRY_DELETE);
        } catch (IOException e) {
            e.printStackTrace();
            return;
        }


        // INSTALL WATCHER THAT LOOKS IF OUR detectFile SHOWS UP IN THE DIRECTORY CHANGES. IF THERE'S A CHANGE, ANOTHER INSTANCE TRIED TO START, SO NOTIFY THE CURRENT ONE OF THAT.
        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) { // To eternity and beyond! Until the universe shuts down. (Should be a volatile boolean, but this class only has absolutely required features.)

            try {
                Thread.sleep(POLLINTERVAL);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }


            final WatchKey wk;
            try {
                wk = watchService.poll();
            } catch (ClosedWatchServiceException e) {
                // This situation would be normal if the watcher has been closed, but our application never does that.
                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();
        }
    }

}

এই সমস্যাটি সমাধান করতে আপনার কয়েকশ লাইন কোডের দরকার নেই। new ServerSocket()ক্যাচ ব্লক সহ যথেষ্ট পর্যাপ্ত,
ব্যবহারকারী 207421

@ ইজেপি আপনি কি স্বীকৃত উত্তরের কথা উল্লেখ করছেন বা আপনি কী সম্পর্কে কথা বলছেন? আমি এক্স-প্ল্যাটফর্ম নো-এক্সট্রা-লাইব্রেরি সমাধানের জন্য বেশ কিছুটা অনুসন্ধান করেছি যা ব্যর্থ হয় না যেমন উদাহরণস্বরূপ যে কিছু সকেট ইতিমধ্যে একটি আলাদা অ্যাপ্লিকেশন দ্বারা দখল করা হয়েছে । যদি এর কোনও সমাধান হয় - বিশেষত আপনি যতটা সুপার সাধারণভাবে উল্লেখ করছেন - তবে আমি এটি সম্পর্কে জানতে চাই।
ড্রিমস্পেসের রাষ্ট্রপতি

@ এজেপি: আমি আবার জিজ্ঞাসা করতে চাই 1) আপনি আমার মাথার সামনে গাজরের মতো ঝোলে যাচ্ছেন এমন কোন তুচ্ছ সমাধানের জন্য আপনি উল্লেখ করছেন, ২) যদি সকেটের সমাধানটি গ্রহণযোগ্য উত্তর দিয়ে শুরু হয় তবে এক বা একাধিক যদি আমার "সকেটের পদ্ধতির অসুবিধাগুলি" বুলেট পয়েন্টগুলি প্রয়োগ হয় এবং 3) যদি তাই হয় তবে কেন এই ত্রুটি থাকা সত্ত্বেও আপনি এখনও আমার মতো একটির উপরে এই পদ্ধতির প্রস্তাব দিবেন।
ড্রিমস্পেসের প্রেসিডেন্ট

@EJP: সমস্যা আপনার ভয়েস, বেশ কিছু ওজন আছে যেমন আপনি কি নিশ্চিতরূপে সচেতন আছি, কিন্তু প্রমাণ যে আমি আছে বাহিনীর আমাকে বিশ্বাস করা যে এখানে আপনার পরামর্শ ভুল। দেখুন, আমি জোর দিচ্ছি না যে আমার সমাধানটি সঠিক এবং সমস্ত কিছু, তবে আমি একটি প্রমাণ ভিত্তিক মেশিন। আপনি দেখতে আপনার অবস্থান আপনি একটি দেয় না দায়িত্ব সম্প্রদায় এই যোগাযোগের অনুপস্থিত ধাঁধা টুকরা পূরণ করার জন্য আপনি শুরু?
ড্রিমস্পেসের রাষ্ট্রপতি

@ ইজেপি: যেহেতু দুঃখজনকভাবে আপনার কাছ থেকে কোনও প্রতিক্রিয়া দেখা যায়নি, তাই আমি এখানে যা সত্য হিসাবে ধরে নেব: সার্ভার সকেট সমাধানের সত্যতা এটি সত্যই গভীরভাবে ত্রুটিযুক্ত এবং সবচেয়ে বেশি যারা এটি বেছে নিয়েছিলেন তার কারণ হতে পারে "অন্যরা এটিও ব্যবহার করুন "", অথবা তারা দায়িত্বহীন লোকদের দ্বারা এটি ব্যবহার করার জন্য প্রতারিত হতে পারে। আমি অনুমান করি যে প্রয়োজনীয় কারণগুলির সাথে আপনি আমাদের কেন সম্মান করলেন না তার একটি অংশটি আপনি তা জানতে পারবেন না / কেন আপনি কখনই এই পদ্ধতির বিষয়ে প্রশ্ন করেননি এবং আপনি এটি প্রকাশ করে কোনও বিবৃতি দিতে চান না make
ড্রিমস্পেসের রাষ্ট্রপতি

1

অনন্য 4j লাইব্রেরিটি জাভা অ্যাপ্লিকেশন এবং পাস বার্তাগুলির একক দৌড়ানোর জন্য ব্যবহার করা যেতে পারে। আপনি এটি https://github.com/prat-man/unique4j এ দেখতে পারেন । এটি জাভা 1.6+ সমর্থন করে।

এটি ফাইল লক এবং গতিশীল পোর্ট লকগুলির সংমিশ্রণটি ব্যবহার করে কেবলমাত্র একটি উদাহরণ চালানোর অনুমতি দেওয়ার প্রাথমিক লক্ষ্য সহ দৃষ্টান্তগুলির মধ্যে সনাক্ত এবং যোগাযোগের জন্য ব্যবহার করে।

নিম্নলিখিতগুলির একটি সাধারণ উদাহরণ নিম্নরূপ:

import tk.pratanumandal.unique4j.Unique4j;
import tk.pratanumandal.unique4j.exception.Unique4jException;

public class Unique4jDemo {

    // unique application ID
    public static String APP_ID = "tk.pratanumandal.unique4j-mlsdvo-20191511-#j.6";

    public static void main(String[] args) throws Unique4jException, InterruptedException {

        // create unique instance
        Unique4j unique = new Unique4j(APP_ID) {
            @Override
            public void receiveMessage(String message) {
                // display received message from subsequent instance
                System.out.println(message);
            }

            @Override
            public String sendMessage() {
                // send message to first instance
                return "Hello World!";
            }
        };

        // try to obtain lock
        boolean lockFlag = unique.acquireLock();

        // sleep the main thread for 30 seconds to simulate long running tasks
        Thread.sleep(30000);

        // try to free the lock before exiting program
        boolean lockFreeFlag = unique.freeLock();

    }

}

দাবি অস্বীকার: আমি ইউনিক 4 জ গ্রন্থাগারটি তৈরি এবং রক্ষণাবেক্ষণ করি।


1

আমি সেই https://sanyarnd.github.io/applocker এর জন্য একটি উত্সর্গীকৃত গ্রন্থাগার লিখেছি

এটি ফাইল-চ্যানেল লকিংয়ের উপর ভিত্তি করে, সুতরাং এটি কোনও পোর্ট নম্বর বা বিদ্যুৎ বিভ্রাটের ক্ষেত্রে ডেডলক অ্যাপ্লিকেশনটিকে ব্লক করবে না (প্রক্রিয়াটি শেষ হয়ে গেলে চ্যানেল প্রকাশিত হয়)।

লাইব্রেরি নিজেই লাইটওয়েট এবং একটি সাবলীল এপিআই রয়েছে।

এটি http://www.sauronsoftware.it/pro پروژې / জুনিকিক / দ্বারা অনুপ্রাণিত হয়েছিল , তবে এটি পরিবর্তে ফাইল চ্যানেলের উপর ভিত্তি করে। এবং অন্যান্য অতিরিক্ত নতুন বৈশিষ্ট্য রয়েছে।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.