2011-08-12 10 views
15

Tôi muốn ngăn người dùng chạy ứng dụng java của tôi nhiều lần song song.Ngăn chặn khởi chạy nhiều phiên bản của một ứng dụng java

Để ngăn chặn điều này, tôi đã tạo một tệp khóa khi mở ứng dụng và xóa tệp khóa khi đóng ứng dụng.

Khi ứng dụng đang chạy, bạn không thể mở một phiên bản jar khác. Tuy nhiên, nếu bạn giết ứng dụng thông qua trình quản lý tác vụ, sự kiện đóng cửa sổ trong ứng dụng sẽ không được kích hoạt và tệp khóa sẽ không bị xóa.

Làm cách nào để đảm bảo phương thức tệp khóa hoạt động hoặc tôi có thể sử dụng cơ chế nào khác?

Trả lời

12

thảo luận tương tự là tại http://www.daniweb.com/software-development/java/threads/83331

Bind một ServerSocket. Nếu nó không ràng buộc thì hãy hủy khởi động. Vì một ServerSocket có thể bị ràng buộc chỉ một lần, chỉ có một instsances duy nhất của chương trình sẽ có thể chạy.

Và trước khi bạn yêu cầu, không. Chỉ vì bạn ràng buộc một ServerSocket, không có nghĩa là bạn đang mở cửa cho lưu lượng mạng. Điều đó chỉ có hiệu lực khi chương trình bắt đầu "lắng nghe" đến cổng với accept().

+1

SPOILER ALERT: sử dụng một ServerSocket – pmnt

+1

Better tóm tắt hơn là chỉ để gửi một liên kết . Nó có thể đã chết sau một thời gian – RobAu

+1

PSA: Một ổ cắm máy chủ hoạt động tốt, đừng quên gán nó vào thứ gì đó sẽ không bị thu gom rác trong suốt quá trình hoặc lợi ích loại trừ sẽ ngắn ngủi (hoặc tệ hơn , nó sẽ hoạt động chỉ đủ lâu để làm cho bạn tự hỏi điều gì đã xảy ra khi nó dừng lại). –

5

Bạn có thể ghi id quá trình của quá trình đã tạo tệp khóa vào tệp. Khi bạn gặp tệp khóa hiện có, bạn không chỉ thoát, nhưng bạn kiểm tra xem quá trình có id đó vẫn còn hoạt động hay không. Nếu không, bạn có thể tiếp tục.

+1

Ý tưởng tuyệt vời! +1. Nhưng ý tưởng này, giữ một tập tin để kiểm tra xem một ứng dụng đang chạy, cảm thấy như một chút xấu xí. Phải không. Không có bất kỳ phương pháp duyên dáng ở tất cả? Tôi không nghĩ rằng đây là phương pháp mà các ứng dụng ** phổ biến khác ** đang sử dụng. Tôi cũng tò mò .. – Anubis

+0

Bạn cũng nên kiểm tra xem quy trình có đúng hay không (hãy tưởng tượng sự cố, khởi động lại máy. Nhưng sau đó, chúng tôi có thể thực hiện tất cả quy trình và có thể loại bỏ việc kiểm tra tệp xấu xí. – Eiko

7

tôi thấy hai tùy chọn bạn có thể thử:

  1. Sử dụng Java shutdown hook
  2. Có tập tin khóa của bạn giữ số tiến trình chính. Quá trình này sẽ tồn tại khi bạn lan một trường hợp khác. Nếu nó không được tìm thấy trong hệ thống của bạn, bạn có thể giả định rằng khóa có thể được loại bỏ và ghi đè.
+0

Điều này thực sự thanh lịch, thậm chí sẽ hoạt động nếu ứng dụng bị treo – Sap

+0

Ngoại trừ khi windows taskmanager giết nó hoặc Linux kill-9 sau đó SOL – JPM

1

.. Tôi có thể sử dụng cơ chế nào khác?

Nếu ứng dụng. có một GUI có thể được khởi chạy bằng cách sử dụng Java Web Start. API JNLP được cung cấp cho web-start cung cấp SingleInstanceService. Đây là số demo. of the SingleInstanceService của tôi.

2

Bạn có thể tạo một ổ cắm máy chủ như

 new ServerSocket(65535, 1, InetAddress.getLocalHost()); 

tại rất đầu mã của bạn. Sau đó, nếu AddressAlreadyInUse ngoại lệ bị bắt trong khối chính, bạn có thể hiển thị thông báo thích hợp.

+1

Nếu ứng dụng khác sử dụng 65535 để gửi dữ liệu, bạn sẽ không liên kết với cổng này, thậm chí không có cá thể nào đang chạy. – ayanamist

1

Bạn có thể viết một cái gì đó như thế này.

Nếu tệp tồn tại, hãy thử xóa nó. nếu nó không thể xóa. Chúng ta có thể nói rằng ứng dụng đang chạy.

Bây giờ, hãy tạo lại cùng một tệp và chuyển hướng sysout và syserr.

này làm việc cho tôi

0

Bạn có thể sử dụng một FileLock, điều này cũng làm việc trong môi trường nhiều người dùng chia sẻ các cảng:

String userHome = System.getProperty("user.home"); 
File file = new File(userHome, "my.lock"); 
try { 
    FileChannel fc = FileChannel.open(file.toPath(), 
      StandardOpenOption.CREATE, 
      StandardOpenOption.WRITE); 
    FileLock lock = fc.tryLock(); 
    if (lock == null) { 
     System.out.println("another instance is running"); 
    } 
} catch (IOException e) { 
    throw new Error(e); 
} 

Cũng sống sót Garbage Collection. Khóa được giải phóng khi quá trình của bạn kết thúc, không quan trọng nếu lối ra hoặc tai nạn thường xuyên hoặc bất cứ điều gì.

0

Đã có sẵn các phương thức java trong lớp File để đạt được điều tương tự. Phương thức này là deleteOnExit() để đảm bảo tệp được tự động xóa khi JVM thoát. Tuy nhiên, nó không phục vụ để buộc phải chấm dứt. Một trong những nên sử dụng FileLock trong trường hợp buộc phải chấm dứt.

Để biết thêm chi tiết kiểm tra, https://docs.oracle.com/javase/7/docs/api/java/io/File.html

Như vậy đoạn mã mà có thể được sử dụng trong phương thức main có thể như:

public static void main(String args[]) throws Exception { 

    File f = new File("checkFile"); 

    if (!f.exists()) { 
     f.createNewFile(); 
    } else { 
     System.out.println("App already running"); 
     return; 
    } 

    f.deleteOnExit(); 

    // whatever your app is supposed to do 
    System.out.println("Blah Blah") 
}