Giới thiệu về Java
Java là một ngôn ngữ lập trình mạnh đang được sử dụng rất rộng rãi hiện nay trên toàn
thế giới. Trên thực tế, Java được biết đến không chỉ là một ngôn ngữ lập trình mà là một
platform – một môi trường và công nghệ phát triển – riêng biệt. Khi làm việc với Java, người
lập trình được sở hữu một thư viện lớn, có tính mở với một lượng mã nguồn tái sử dụng
khổng lồ luôn có trên internet. Ngoài ra, các chương trình viết bằng Java có môi trường thực
thi riêng với các tính năng bảo mật, khả năng triển khai trên nhiều hệ điều hành khác nhau và
nhiều tính năng ưu việt khác chúng ta sẽ xem xét trong phần sau.
I.2 Tóm tắt lịch sử hình thành của Java
Năm 1991, một nhóm kỹ sư của hãng SUN bao gồm Patrick Naughton, Sun Fellow và
James Gosling có ý tưởng phát minh ra một ngôn ngữ lập trình nhỏ gọn có thể thực thi được
trên các thiết bị dạng như bộ chuyển kênh của truyền hình cáp vì các thiết bị kiểu này có bộ
nhớ nhỏ. Bên cạnh đó, do các hãng khác nhau sử dụng các chíp xử lý (CPUs) khác nhau nên
một đặc tính quan trọng mà ngôn ngữ này phải có là độc lập với các dòng CPUs khác nhau –
gọi là đặc tính di động. Nhóm đã mở một dự án có tên là Green để hiện thực hóa ý tưởng này.
Để giải quyết vấn đề di động, nhóm đã sử dụng ý tưởng của kỹ sư Niklaus Wirth –
người sáng lập ngôn ngữ Pascal – về việc sử dụng cơ chế thông dịch và máy ảo (virtual
machine).
151 trang |
Chia sẻ: tlsuongmuoi | Lượt xem: 2515 | Lượt tải: 2
Bạn đang xem trước 20 trang tài liệu Lịch sử hình thành và phát triển ngôn ngữ lập trình Java, để xem tài liệu hoàn chỉnh bạn click vào nút DOWNLOAD ở trên
tateChange đ bi t đ c ch s c aử ụ ố ố ươ ứ ể ế ượ ỉ ố ủ
ph n t đang thay đ i tr ng thái. ầ ử ổ ạ
Đ x lý đ c tình hu ng nh p đôi chu t, ta cài đ t giao ti p ActionListener và g n nóể ử ượ ố ấ ộ ặ ế ắ
vào danh sách.
Ph ng th c getActionCommand() trong ActionEvent s tr v tên c a ph n t bươ ứ ẽ ả ề ủ ầ ử ị
nh p.ấ
// Java core packages
import java.awt.*;
// Java extension packages
import javax.swing.*;
import javax.swing.event.*;
public class ListTest extends JFrame {
private JList colorList;
private Container container;
private String colorNames[] = { "Black", "Blue", "Cyan", "Dark Gray", "Gray", "Green",
"Light Gray", "Magenta", "Orange", "Pink", "Red", "White", "Yellow" };
124
private Color colors[] = { Color.black, Color.blue, Color.cyan, Color.darkGray,
Color.gray, Color.green, Color.lightGray, Color.magenta, Color.orange, Color.pink, Color.red,
Color.white, Color.yellow };
// Thi t l p GUIế ậ
public ListTest()
{
super( "List Test" );
// l y layoutấ
container = getContentPane();
container.setLayout( new FlowLayout() );
// T o danh sáchạ
colorList = new JList( colorNames );
colorList.setVisibleRowCount( 5 );
// Không cho ch n nhi uọ ề
colorList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION );
// thêm m t JScrollPane ch a danh sáchộ ứ
container.add( new JScrollPane( colorList ) );
// đ t l ng nghe s ki nặ ắ ự ệ
colorList.addListSelectionListener( new ListSelectionListener() {
public void valueChanged( ListSelectionEvent event )
{
container.setBackground( colors[ colorList.getSelectedIndex() ] );
} } );
setSize( 350, 150 );
setVisible( true );
}
// hàm main
public static void main( String args[] )
{
ListTest application = new ListTest();
application.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
} }
III.7 Ô văn b n (text field) và vùng văn b n (text areas)ả ả
T o ô văn b n:ạ ả
• Kh i t o m t ô văn b n không xác đ nh kích th c:ở ạ ộ ả ị ướ public TextField();
• T o m t ô văn b n hi n th t i thi u numCols ký t :ạ ộ ả ể ị ố ể ự public TextField(int
numCols);
125
• T o m t ô văn b n v i n i dung là m t chu i cho tr c: public TextFiled(Stringạ ộ ả ớ ộ ộ ỗ ướ
initText);
• T o ô văn b n k t h p: public TextField(String initText, int numCols);ạ ả ế ợ
• T o vùng văn b n:ạ ả
• T o vùng văn b n r ng, kích th c b t kỳ: public TextArea();ạ ả ỗ ướ ấ
• T o m t vùng văn b n v i n i dung cho tr c: public TextArea(Stringạ ộ ả ớ ộ ướ
initiaText);
• T o m t vùng văn b n v i s c t và s dòng đ nh tr c: public TextArea(intạ ộ ả ớ ố ộ ố ị ướ
rows, int cols);
• T o m t vùng văn b n v i s dòng s c t và n i dung cho tr c: publicạ ộ ả ớ ố ố ộ ộ ướ
TextArea(String st, int rows, int cols)
Đ c đi m chung c a các thành ph n văn b nặ ể ủ ầ ả :
Hai l p này đ c d n xu t t l p TextComponentớ ượ ẫ ấ ừ ớ
Mu n đ a n i dung văn b n vào các đ i t ng này ta s d ng ph ng th c setText:ố ư ộ ả ố ượ ử ụ ươ ứ
public void setText(String newText);
L y n i dung văn b n trong các đ i t ng: public String getText();ấ ộ ả ố ượ
L y n i dung văn b n đ c đánh d u: public String getSelectedText();ấ ộ ả ượ ấ
Đ xác đ nh xem v trí đánh d u kh i văn b n b t đ u và k t thúc đâu: public intể ị ị ấ ố ả ắ ầ ế ở
getSelectionStart(); //đ uầ
public int getSelectionEnd(); //cu iố
Đánh d u toàn b văn b n: public void selectAll();ấ ộ ả
Cho phép so n th o đ c: public void setEditable(boolean canEdited); canEdited =ạ ả ượ
false: ch đ c.ỉ ọ
canEdited = true: thêm, s đ c.ử ượ
Xác đ nh đ i t ng đang trang thái nào: public boolean isEditable();ị ố ượ ở
Đ c đi m riêng c a TextField:ặ ể ủ
Đ t ký t hi n th cho ký t nh p vào: public void setEchoChar(Char ch); ví d :ặ ự ể ị ự ậ ụ
myTextField.setEchoChar('*'); //mã mKh uẩ
Xác đ nh xem ký t làm ký t hi n th : public char getEchoChar();ị ự ự ể ị
Xác đ nh chi u dài c a ô văn b n theo ký t : public int getColums();ị ề ủ ả ự
Đ c đi m riêng c a đ i t ng TextArea:ặ ể ủ ố ượ
Đ a thêm m t dòng văn b n vào đ i t ng:ư ộ ả ố ượ public void appendText(String
newText);
Chèn m t chu i văn b n vào v trí b t kỳ: public void insertText(String newText, intộ ỗ ả ị ấ
pos);
Xác đ nh kích th c hi n th :ị ướ ể ị public int getRows(); public int getColums();
S d ng đ i t ng TextField và TextArea:ử ụ ố ượ
Mu n l y n i dung văn b n c a đ i t ng, ta thi t l p ActionListener đ g n đ iố ấ ộ ả ủ ố ượ ế ậ ể ắ ố
t ng x lý tình hu ng vào văn b n TextField. Khi ng i dung nh n Enter thì tình hu ngượ ử ố ả ườ ấ ố
đ c g i.ượ ọ
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class TextFieldTest extends JFrame {
private JTextField textField1, textField2, textField3;
private JPasswordField passwordField;
126
// Thi t l p giao di n GUIế ậ ệ
public TextFieldTest()
{
super( "Testing JTextField and JPasswordField" ); // constructor c a JFrameủ
Container container = getContentPane();
container.setLayout( new FlowLayout() );
// ô nh p v i kích th c m c đ nhậ ớ ướ ặ ị
textField1 = new JTextField( 10 );
container.add( textField1 );
// ô nh p v i văn b n có s nậ ớ ả ẵ
textField2 = new JTextField( "Enter text here" );
container.add( textField2 );
// ô nh p không cho phép nh p, ch hiên th thông tinậ ậ ỉ ị
textField3 = new JTextField( "Uneditable text field", 20 );
textField3.setEditable( false );
container.add( textField3 );
// ô nh p passwordậ
passwordField = new JPasswordField( "Hidden text" );
container.add( passwordField );
// Đăng ký b l ng nghe s ki nộ ắ ự ệ
TextFieldHandler handler = new TextFieldHandler();
textField1.addActionListener( handler );
textField2.addActionListener( handler );
textField3.addActionListener( handler );
passwordField.addActionListener( handler );
setSize( 325, 100 );
setVisible( true );
}
// hàm main
public static void main( String args[] )
{
TextFieldTest application = new TextFieldTest();
application.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
}
// L p n i cho b l ng nghe s ki nớ ộ ộ ắ ự ệ
private class TextFieldHandler implements ActionListener {
// ph ng th c x lý s ki nươ ứ ử ự ệ
public void actionPerformed( ActionEvent event )
{
String string = "";
// khi ng i dùng n enterườ ấ
127
if ( event.getSource() == textField1 )
string = "textField1: " + event.getActionCommand();
// user pressed Enter in JTextField textField2
else if ( event.getSource() == textField2 )
string = "textField2: " + event.getActionCommand();
// user pressed Enter in JTextField textField3
else if ( event.getSource() == textField3 )
string = "textField3: " + event.getActionCommand();
// user pressed Enter in JTextField passwordField
else if ( event.getSource() == passwordField ) {
JPasswordField pwd = ( JPasswordField ) event.getSource();
string = "passwordField: " + new String( passwordField.getPassword() );
}
JOptionPane.showMessageDialog( null, string ); // Hiên th c a s thông báoị ử ổ
}
}
}
III.8 Thanh tr t (Scrollbar)ượ
Ta có th đ t thanh tr t các giá tr gi i h n t i thi u (min) và t i đa (max) cùng v i vể ặ ượ ị ớ ạ ố ể ố ớ ị
trí hi n t i trên thanh tr t.ệ ạ ượ
Khi ng i dùng kích chu t vào mũi tên hai đ u thì tình hu ng line n y sinh, thanhườ ộ ở ầ ố ả
tr t s t đ ng c ng thêm hay tr đi m t đ n v .ượ ẽ ự ộ ộ ừ ộ ơ ị
Tình hu ng page n y sinh khi ng i dùng kích chu t vào kho ng gi a thanh tr t, vố ả ườ ộ ả ữ ượ ị
trí hi n hành s thay đ i.ệ ẽ ổ
Tình hu ng absolute n y sinh khi ng i dùng n m vào v trí hi n hành c a thanh tr tố ả ườ ắ ị ệ ủ ượ
và kéo nó đi.
Đ i t ng Scrollbar ch ch u trách nhi m di chuy n và cung c p cho ta giá tr thay đ i.ố ượ ỉ ị ệ ể ấ ị ổ
T o thanh tr t:ạ ượ
Ph ng th c kh i t o: public Scrollbar();ươ ứ ở ạ
T o thanh tr t đ ng hay ngang ta dùng: public Scrollbar(int orienttation); orienttationạ ượ ứ
nh n giá tr Scrollbat.VERTICAL - cho đ ng, Scrollbar.HORIZONTAL cho n m ngang.ậ ị ứ ằ
T o thanh tr t có đ y đ thông s ban đ u:ạ ượ ầ ủ ố ầ
public Scrollbar(int orienttation,
int pos, //v trí kh i đ uị ở ầ
int pageUnit, //b c nh yướ ả
int minValue, //giá tr minị
int maxValue); //giá tr maxị
M t s ph ng th c hay dùng:ộ ố ươ ứ
Thay đ i giá tr tăng gi m (m c đ nh là 1): public void setUnitIncrement(int increment);ổ ị ả ặ ị
Mu n bi t hi n th i tăng gi m bao nhiêu: public int getUnitIncrement()ố ế ệ ờ ả
128
Ch đ nh con s khi tình hu ng page x y ra:ỉ ị ố ố ả pubic void setBlockIncrement(int b);
Mu n bi t hi n th i đ n v thay đ i là bao nhiêu: public int getBlockIncrement();ố ế ệ ờ ơ ị ổ
L y giá tr l n nh t và nh nh t: public int getMaximum(); public int getMinimum();ấ ị ớ ấ ỏ ấ
Đ t l i v trí hi n hành cho thanh tr t: public void setValue(int newPos);ặ ạ ị ệ ượ
Cho ta v trí hi n hành: public int getValue();ị ệ
Mu n bi t thanh tr t đ ng hay ngang: public int getOrientation() tr v giá tr là m tố ế ượ ứ ả ề ị ộ
trong hai h ng s Scrollbar.VERTICAL và Scrollbar.HORIZONTAL.ằ ố
Thi t l p l i các thông s cho thanh tr t: public void setValues(int position, intế ậ ạ ố ượ
pageUnit, int minimum, int maximum);
ví d :ụ myScrollbar.setValues(75, 10, 0, 500);
S d ng thanh tr t:ử ụ ượ
Ta nh đ i t ng x lý tình hu ng x lý: public voidờ ố ượ ử ố ử
adjustmentValueChanged(AdjustmentEvent evt);
Có 3 tr ng thái: line, page và absolute. Ta s d ng hàm getAdjustmentType() đ xácạ ử ụ ể
đ nh xem tình hu ng nào đang x y ra.ị ố ả
AdjustmentEvent.UNIT_INCREMENT: tình hu ng line x y ra, v trí thanh tr t tăng 1ố ả ị ượ
đ n v .ơ ị
AdjustmentEvent.UNIT_DECREMENT: tình hu ng line x y ra, v trí thanh tr t gi mố ả ị ượ ả
1 đ n v .ơ ị
AdjustmentEvent.BLOCK_INCREMENT: tình hu ng page x y ra, v trí hi n hành tăngố ả ị ệ
1 đv.
AdjustmentEvent.Track: tình hu ng absolute x y ra, ta l y v trí thanh tr t b ng hàmố ả ấ ị ượ ằ
getValue().
IV. Thành ph n Menuầ
L p JMenuBar cài đ t thanh th c đ n và trong đó có th ch a các th c đ n pull-down.ớ ặ ự ơ ể ứ ự ơ
Các JMenuBar đ c t o ra đ g n vào m t c a s JFrame b ng m t l nh g i:ượ ạ ể ắ ộ ủ ổ ằ ộ ệ ọ
JMenuBar menuBar = new JMenuBar();
JFrame frm = new JFrame(“Day la mot Frame”);
frm.setJMenuBar(menuBar); // MenuBar này ch a có ph n t nàoư ầ ử
Sau khi có MenuBar, ta c n thêm vào đó các JMenu là các m c trên thanh Menu, khiầ ụ
ng i dùng ch n vào đó s s xu ng danh sách các m c ch n khác.ườ ọ ẽ ổ ố ụ ọ
JMenu file = new JMenu(“File”);
Ta đ t cho nó m t phím t t, ví d là ‘F’ đ khi n Alt + F thì JMenu này đ c kíchặ ộ ắ ụ ể ấ ượ
ho t:ạ
file.setMnemonic('F');
Sau đó thì thêm nó vào JMenuBar: menuBar.add(file);
Bây g i là lúc ta cài đ t các m c ch n trong m t JMenu. Java dùng l p JMenuItem đ nhờ ặ ụ ọ ộ ớ ị
nghĩa t ng m c c a th c đ n.ừ ụ ủ ự ơ
JMenuItem open = new JMenuItem(“Open”,’O’);
đây ta đã g i m t constructor v i m t tham s là nhãn c a m c ch n, m t tham s làỞ ọ ộ ớ ộ ố ủ ụ ọ ộ ố
ký t phím t t. Sau đó ta add vào JMenu:ự ắ
file.add(open);
N u ta c n bi u di n các dòng k ngang đ phân tách các m c ch n thì ta có th g iế ầ ể ễ ẻ ể ụ ọ ể ọ
ph ng th c addSeparator() c a m t đ i t ng JMenu:ươ ứ ủ ộ ố ượ
file.addSeparator();
129
L p JPopUpMenu bi u di n cho th c đ n pop-up. Nh ng th c đ n này có th xu tớ ể ễ ự ơ ữ ự ơ ể ấ
hi n b t c v trí nào trong c a s hi n t i.ệ ấ ứ ị ử ổ ệ ạ
L p JCheckBoxMenuItem ch a các m c đ c ch n đ ki m tra trong các m c th cớ ứ ụ ượ ọ ể ể ụ ự
đ n.ơ
T o thanh trình đ n: JMenuBar myMenubar = new JMenuBar();ạ ơ
Đ t tr ng thái cho m i m c ch n s d ng enable() ho c disable():ặ ạ ỗ ụ ọ ử ụ ặ
Vi d : openItem.enable();ụ //đ c ch nượ ọ
openItem.disable(); //m m c ch nờ ụ ọ
Ta có th dùng đ ng phân cách đ tách các m c ch n:ể ườ ể ụ ọ
FileMenu.addSeparator();
T o m c ch n có ch a menu con khác, ta t o m t menu bình th ng r i đ a vào ạ ụ ọ ứ ạ ộ ườ ồ ư
menu đã có.
Ví d :ụ
//t o m c ch n có menu conạ ụ ọ
JMenu printItem = new JMenu("Print");
//t o các m c ch n cho menu conạ ụ ọ
printItem.add("Print preview");
printItem.add("to preview");
//đ a m c ch n có menu con vào menu chínhư ụ ọ
FileMenu.add(printItem);
T o m t m c ch n có kh năng đánh d u (check Item), m t d u ki m tra (check mark)ạ ộ ụ ọ ả ấ ộ ấ ể
s hi n bên trái m c ch n:ẽ ệ ụ ọ
M c đánh d u: CheckboxMenuItem Autosave = new CheckboxMenuItem("Auto save");ụ ấ
FileMenu.add(Autosave);
Xác đ nh xem m c ch n Autosave đang tr ng thái nào, ta dùng: Autosave.getState();ị ụ ọ ở ạ
Khi s d ng, đ m c ch n t ng tác và nh n đ c s ki n ta c n cài đ t giao di nử ụ ể ụ ọ ươ ậ ượ ự ệ ầ ặ ệ
ActionListener và g n vào t ng m c ch n.ắ ừ ụ ọ
Sau đây là m t ví d xây d ng m t JFrame v i thanh menu và các m c ch n trong đóộ ụ ự ộ ớ ụ ọ
có cài đ t x lý các s ki n.ặ ử ự ệ
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
class MenuBarSample extends JFrame {
//Khai bao mot hop thoai
JOptionPane op = new JOptionPane();
// Khai bao mot thuc don pop-up
JPopupMenu jp;
public MenuBarSample()
{
// Lay ve doi tuong chua cua Frame hien tai
Container pane = this.getContentPane();
// Dat kieu trinh bay
pane.setLayout(new FlowLayout(FlowLayout.LEADING));
// Khai bao mot thanh menu
JMenuBar menuBar= new JMenuBar();
// Khai bao muc File trong thanh menu
JMenu menuFile= new JMenu("File");menuBar.add(menuFile);
130
// Dat ky tu kich hoat tat cung Alt
menuFile.setMnemonic('F');
// Khai bao mot muc chon voi phim tat O
JMenuItem fileOpen = new JMenuItem("Open",'O');
// Them muc chon vao muc File
menuFile.add(fileOpen);
// Them mot muc chon khac voi phim tat N
menuFile.add(new JMenuItem("New",'N'));
// Them dong ngan cach
menuFile.addSeparator();
// Them mot muc chon co ten Save
menuFile.add("Save");
// Xu ly su kien chon muc Open
fileOpen.addActionListener( new ActionListener()
{
public void actionPerformed(ActionEvent event)
{
// Hien thi thong bao, getContentPane() de lay Container cua Frame
op.showMessageDialog(getContentPane(),"Ban vua chon Open");
}
} );
// Xu ly su kien chon New
menuFile.getItem(1).addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent event)
{
op.showMessageDialog(getContentPane(),"Ban vua chon New");
}
} );
// Xu ly su kien chon Save
menuFile.getItem(3).addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent event)
{
op.showMessageDialog(getContentPane(),"Ban vua chon Save");
}
} );
// Khai bao mot muc chon kieu checkbox
JCheckBoxMenuItem chk = new JCheckBoxMenuItem("is editting");
// Them phan xu ly su kien chon hay khong chon cho no
chk.addActionListener( new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
// Lay ve doi tuong nguon su kien va ep kieu
JCheckBoxMenuItem ck = (JCheckBoxMenuItem)e.getSource();
if (ck.isSelected())
131
//Neu duoc chon
op.showMessageDialog(getContentPane(),"Ban vua chon is editting");
else
// Neu khong duoc chon
op.showMessageDialog(getContentPane(),"Ban vua bo chon is editting");
}
} );
// Them muc chon checkbox vao menu File
menuFile.add(chk);
// Dat thanh Menu cho Frame la doi tuong menuBar
this.setJMenuBar(menuBar);
// Cap phat bo nho cho popup menu
jp = new JPopupMenu("Popup");
jp.add("Create");
jp.addSeparator();
jp.add("New Document");
this.addMouseListener( new MouseAdapter()
{
public void mouseClicked(MouseEvent e)
{
if( (e.getModifiers() & InputEvent.BUTTON3_MASK)== InputEvent.BUTTON3_MASK)
jp.show(getContentPane(),e.getX(),e.getY());
}
}
);
}
public static void main(String[] argvs)
{
MenuBarSample m = new MenuBarSample();
m.setSize(300,400);
m.setVisible(true);
}
}
V. B qu n lý cách trình bày (Layout Manager)ộ ả
Dùng đ s p x p ch và đ nh v cho các đ i t ng GUI.ể ắ ế ỗ ị ị ố ượ
Có 5 cách trình bày:
• FlowLayout: s p x p các đ i t ng t trái qua ph i và t trên xu ng d i. Cácắ ế ố ượ ừ ả ừ ố ướ
đ i t ng gi nguyên kích th c.ố ượ ữ ướ
• GridLayout: t o m t khung l i vô hình v i các ô b ng nhau, các đ i t ng sạ ộ ướ ớ ằ ố ượ ẽ
đ t v a kích th c v i các ô đó.ặ ừ ướ ớ
• BorderLayout: Các đ i t ng đ c đ t theo đ ng vi n c a khung ch a theoố ượ ượ ặ ườ ề ủ ứ
các c nh West, East, South, Nort và Center.ạ
• CardLayout: Các đ i t ng đ c đ t v a v n v i khung ch a và n m ch ngố ượ ượ ặ ừ ặ ớ ứ ằ ồ
lên nhau nh các lá bài.ư
132
• GridBadLayout: các đ i t ng trong khung ch a cũng đ c đ a vào các ô c aố ượ ứ ượ ư ủ
m t khung l i vô hình, kích th c các đ i t ng không nh t thi t ph i v aộ ướ ướ ố ượ ấ ế ả ừ
m t ô.ộ
Mu n áp d ng ta t o ra đ i t ng trên r i chuy n nó cho khung ch a.ố ụ ạ ố ượ ồ ể ứ
Ví du: FlowLayout objectsLayout = new FlowLayout();
myWindow.setLayout(objectsLayout);
hay có th vi t g n h n:ể ế ọ ơ
myWindow.setLayout(new FlowLayout());
V.1 Cách trình bày FlowLayout:
T o đ i t ng FlowLayout, ta s d ng ph ng th c: public FlowLayout();ạ ố ượ ử ụ ươ ứ
ho c ch đ nh luôn cách căn l b ng ph ng th c kh i t o: public FlowLayout(intặ ỉ ị ề ằ ươ ứ ở ạ
align);
align là FlowLayout.LEFT, FlowLayout.RIGHT, FlowLayout.CENTER ho c ch ra kho ng cácặ ỉ ả
gi a các đ i t ng trên cùng m t hàng: public FlowLayout(int align, int hgap, int vgap); ữ ố ượ ộ
V.2 Cách trình bày GridLayout:
Ph ng th c kh i t o: public GridLayout(int Rows, int Cols);ươ ứ ở ạ
Ví d :ụ GridLayout layout = new GridLayout(3, 2);
Xác đ nh kho ng cách gi a các đ i t ng qu n lý:ị ả ữ ố ượ ả
public GridLayout(int Rows, int Cols, int hgap, int vgap);
V.3 Cách trình bày BorderLayout
Đ i t ng đ c đ t theo đ ng vi n khung ch a, theo các c nh c a khung.ố ượ ượ ặ ườ ề ứ ạ ủ
T o b qu n lý ki u BorderLayout:ạ ộ ả ể public BorderLayout();
Ví d :ụ myWindow.setLayout(new BorderLayout());
Khi đ a đ i t ng vào khung ch a, ta ph i đ nh hình tr c đ i t ng đó đ t đâu:ư ố ượ ứ ả ị ướ ố ượ ặ ở
myWindow.add("North", new Button("on Top"));
có 5 ki u: "North", "South", "West", "East", "Center".ể
VI. Các h p tho iộ ạ
VI.1 H p tho i thông báoộ ạ
Khi c n đ a ra thông báo hay h i ng i dùng m t v n đ gì đó và nh n v câu tr l i,ầ ư ỏ ườ ộ ấ ề ậ ề ả ờ
ta dùng h p tho i thông báo. Java h tr l p JOptionPane đ ta th c hi n công vi c này.ộ ạ ỗ ợ ớ ể ự ệ ệ
L p JOptionPane có 4 ph ng th c tĩnh sau:ớ ươ ứ
Tên ph ng th cươ ứ Giá tr trị ả
về
Ý nghĩa
showMessageDialog Không có Hi n th m t thông báo và đ i n OKể ị ộ ợ ấ
showConfirmDialog S intố Hi n th thông báo và đ i xác nh n Ok hay Cancelể ị ợ ậ
showOptionDialog S intố Hi n th thông báo và nh n v tr l i t m t danh sáchể ị ậ ề ả ờ ừ ộ
ch nọ
showInputDialog Chu iỗ Hi n th thông báo và nh n v m t dòng do user nh p vàoể ị ậ ề ộ ậ
133
icon hi n th ph thu c vào lo i thông báo:ể ị ụ ộ ạ
ERROR_MESSAGE : Thông báo l iỗ
INFORMATION_MESSAGE : Thông tin
WARNING_MESSAGE :C nh báoả
QUESTION_MESSAGE: H iỏ
PLAIN_MESSAGE: Gi i thíchả
Các h ng s này đ c truy c p qua JOptionPane.ằ ố ượ ậ
Ví d :ụ
int selection = JOptionPane.showConfirmDialog(parent, "Message", "Title",
JOptionPane.OK_CANCEL_OPTION, JOptionPane.WARNING_MESSAGE);
if (selection == JOptionPane.OK_OPTION) . . .
VI.2 H p tho i ch n Fileộ ạ ọ
Khi vi t ng d ng ta g p các tình hu ng m file đ đ c ho c ghi. Swing h tr m tế ứ ụ ặ ố ở ể ọ ặ ỗ ợ ộ
l p JFileChooser đ ta th c hi n công vi c này. Hai ph ng th c quan tr ng là:ớ ể ự ệ ệ ươ ứ ọ
- showOpenDialog: Đ hi n th h p tho i ch n m fileể ệ ị ộ ạ ọ ở
- showSaveDialog: Đ hi n th h p tho i ch n ghi fileể ệ ị ộ ạ ọ
Sau đây là các b c đ làm vi c v i h p tho i ch n file:ướ ể ệ ớ ộ ạ ọ
1- T o m t đ i t ng JFileChooser: JFileChooser chooser = new JFileChooser();ạ ộ ố ượ
2- Đ t th m c cho h p tho i: chooser.setCurrentDirectory(new File("."));ặ ư ụ ộ ạ
3- N u đ nh ch n tr c m t file, có th đ t: chooser.setSelectedFile(newế ị ọ ướ ộ ể ặ
File(filename));
4- Đ cho phép ch n nhi u file: chooser.setMultiSelectionEnabled(true);ể ọ ề
5- N u mu n gi i h n ki u file, dùng b l c file. Đ dùng đ c b l c file ta ph iế ố ớ ạ ể ộ ọ ể ượ ộ ọ ả
thi t k m t l p k th a t l p javax.swing.filechooser.FileFilter. Ví d b l c file Gif:ế ế ộ ớ ế ừ ừ ớ ụ ộ ọ
public class GifFilter extends FileFilter
{
public boolean accept(File f)
{
return f.getName().toLowerCase().endsWith(".gif") || f.isDirectory();
}
public String getDescription()
{
return "GIF Image";
}
}
Sau đó gán cho h p tho i: chooser.setFileFilter(new GifFilter());ộ ạ
134
6- M c đ nh thì ch cho phép ch n file, n u mu n cho phép ch n th m c dùng ph ngặ ị ỉ ọ ế ố ọ ư ụ ươ
th c: setFileSelectionMode() v i các tham s : JFileChooser.DIRECTORIES_ONLY ho cứ ớ ố ặ
JFileChooser.FILES_AND_DIRECTORIES.
7- Hi n th h p tho i b ng l nh g i:ể ị ộ ạ ằ ệ ọ
int result = chooser.showOpenDialog(parent);
ho cặ
int result = chooser.showSaveDialog(parent);
Các giá tr tr v là JFileChooser.APPROVE_OPTION,ị ả ề
JFileChooser.CANCEL_OPTION, or JFileChooser.ERROR_OPTION
8- L y vè file ho c các file đ c ch n dùng: getSelectedFile() ho c getSelectedFiles().ấ ặ ượ ọ ặ
Neus ch mu n l y tên file thì ta dùng ph ng th c getPath().ỉ ố ấ ươ ứ
String filename = chooser.getSelectedFile().getPath();
VI.3 H p tho i ch n màuộ ạ ọ
Swing h tr l p JColorChooser đ ng i dùng ch n màu. Cú pháp s d ng nh sau:ỗ ợ ớ ể ườ ọ ử ụ ư
Color selectedColor = JColorChooser.showDialog(parent,title, initialColor);
Khi làm vi c v i h p tho i ch n màu ta c n cung câp:ệ ớ ộ ạ ọ ầ
- parent: m t companent cha; ộ
- title: Tiêu đ h p tho i; ề ộ ạ
- ch đ h p tho i modal hay modeless; ế ộ ộ ạ
- m t đ i t ng ch n màu ộ ố ượ ọ
- b l ng nghe cho nút b m Ok và Cancel.ộ ắ ấ
chooser = new JColorChooser();
dialog = JColorChooser.createDialog(parent,"Background Color", false /* not modal */, chooser,
new ActionListener() // L ng nghe cho OKắ
{
public void actionPerformed(ActionEvent event)
{
setBackground(chooser.getColor());
}
},
null /* Không có l ng nghe cho Cancel */);ắ
Bài t pậ
1. Hãy thi t k m t giao di n có n i dung nhế ế ộ ệ ộ ư sau:
135
2. Hãy l p trình đ x lý s ki n click chu t ph i lên n n c a s s hi n m t menu Popup.ậ ể ử ự ệ ộ ả ề ủ ổ ẽ ệ ộ
3. Vi t ch ng trình gi i ph ng trình b c 2 v i giao di n GUI. Yêu c u ch ng trình có cácế ươ ả ươ ậ ớ ệ ầ ươ
ô nh p các h s a, b, c và cho phép xem k t qu . Tr ng h p không có nghi m s hi n thậ ệ ố ế ả ườ ợ ệ ẽ ể ị
m t h p tho i thông báo “ch ng trình vô nghi m”.ộ ộ ạ ươ ệ
136
Đ tài 11. Threadingề
Java là ngôn ng thông d ng duy nh t h tr cho l p trình viên các gi i pháp l p trìnhữ ụ ấ ỗ ợ ậ ả ậ
song song. L p trình viên xác đ nh s l ng các thread đ c ch y trong ch ng trình và chúngậ ị ố ượ ượ ạ ươ
đ c th c hi n song song v i nhau nh ng giai đo n nào. Kh năng này c a Java g i là tínhượ ự ệ ớ ở ữ ạ ả ủ ọ
đa lu ng.ồ
I. Khái ni m threadệ
I.1 Khái ni m:ệ
Thread – lu ng ch m t đ n v ch ng trình có th tách kh i các ph n khác c aồ ỉ ộ ơ ị ươ ể ỏ ầ ủ
ch ng trình đ th c hi n song song v i các ph n khác t ng kho ng th i gian ho c trongươ ể ự ệ ớ ầ ở ừ ả ờ ặ
toàn b quá trình nó th c hi n. ộ ự ệ
Trong m i ch ng trình Java, có m t lu ng chính đ c b t đ u b ng vi c g i hàmỗ ươ ộ ồ ượ ắ ầ ằ ệ ọ
main(), các lu ng khác có th phát sinh t lu ng chính này. Các câu l nh trong hàm main() n uồ ể ừ ồ ệ ế
không đ c đ a vào m t lu ng riêng thì s đ c th c hi n tu n t .ượ ư ộ ồ ẽ ượ ự ệ ầ ự
I.2. L p Threadớ
L p Thread trong gói java.lang có m t s constructor:ớ ộ ố
Public Thread ()
Public thread(): Khi này thread s có tên là Thread_1, Thread_2,….ẽ
Các công vi c c a m t thread đ c đ t trong ph ng th c run(). Ph ng th c này cóệ ủ ộ ượ ặ ươ ứ ươ ứ
th đ c khai báo ch ng trong l p khai báo k th a Thread ho c khai báo cài đ t giao di nể ượ ồ ớ ế ừ ặ ặ ệ
Runable.
Ng i l p trình b t đ u m t thread b ng các g i ph ng th c start(), ph ng th cườ ậ ắ ầ ộ ằ ọ ươ ứ ươ ứ
start() sau đó s g i run(). Sau khi start() th c hi n xong, nó tr v đi u khi n cho ch ngẽ ọ ự ệ ả ề ề ể ươ
trình g i nó. Do đó, ch ng trình g i nó và thread đ c th c hi n m t cách đ ng th i.ọ ươ ọ ượ ự ệ ộ ồ ờ
• Ph ng th c start() s ném ra m t ng o i l IllegalThreadStateException n uươ ứ ẽ ộ ạ ệ ế
thread c n b t đ u đã b t đ u r i.ầ ắ ầ ắ ầ ồ
• Ph ng th c tĩnh sleep c a Thread đ c g i v i m t tham s xác đ nh r ngươ ứ ủ ượ ọ ớ ộ ố ị ằ
m t thread đang ch y s d ng l i trong bao lâu theo đ n v ph n nghìn giây.ộ ạ ẽ ừ ạ ơ ị ầ
Trong khi m t thread “sleep”, nó s không tiêu t n tài nguyên CPU và threadộ ẽ ố
khác có th ch y.ể ạ
• Ph ng th c interrupt() đ c g i đ đ ng t m t thread. Ph ng th c này trươ ứ ượ ọ ể ể ắ ộ ươ ứ ả
v true n u ng t thành công. Ph ng th c isInterrupted() dùng đ ki m tra xemề ế ắ ươ ứ ể ể
thread có b ng t hay không.ị ắ
• Ph ng th c isAlive() tr v true n u start() đã đ c g i và ph ng th c run()ươ ứ ả ề ế ượ ọ ươ ứ
v n đang th c hi n.ẫ ự ệ
• Ph ng th c setName() đ t tên cho m t thread, getName() l y tên m t thread.ươ ứ ặ ộ ấ ộ
Ph ng th c toString() tr v tên ph ng th c, đ u tiên và nhóm c a thread.ươ ứ ả ề ươ ứ ộ ư ủ
• Ph ng th c static currentThread() tr v tham chi u t i thread hi n hành đangươ ứ ả ề ế ớ ệ
th c hi n.ự ệ
• Ph ng th c joint đ i (ươ ứ ợ wait) m t ph n h i c a m t thông đi p đ c g i điộ ả ổ ủ ộ ệ ượ ử
tr c khi th c hi n thread.ướ ự ệ
137
I.3 Các b c đ t o m t threadướ ể ạ ộ
Sau đây là các b c đ n gi n đ th c hi n m t nhi m v trong m t thread riêng:ướ ơ ả ể ự ệ ộ ệ ụ ộ
1. Khai báo m t l p có cài đ t giao di n Runable v i ph ng th c run() đ c đ nhộ ớ ặ ệ ớ ươ ứ ượ ị
nghĩa:
class MyRunnable implements Runnable
{
public void run()
{
// code th c hi nự ệ
}
}
2. T o m t đ i t ng c a l pạ ộ ố ượ ủ ớ
Runnable r = new MyRunnable();
3. T o m t đ i t ng Thread t đ i t ng Runable trên:ạ ộ ố ượ ừ ố ượ
Thread t = new Thread(r);
4. G i ph ng th c start()ọ ươ ứ
t.start();
M t thread cũng có th đ c t o ra b ng cách xây d ng m t l p con c a l p Thread:ộ ể ượ ạ ằ ự ộ ớ ủ ớ
class MyThread extends Thread
{
public void run()
{
// code c a threadủ
}
}
Sau đó ta cũng làm theo các b c 2,3 và 4 đ th c hi n thread.ướ ể ự ệ
II. Các tr ng thái c a thread.ạ ủ
• Tr ng thái born: Khi thread ch a g i start().ạ ư ọ
• Tr ng thái ready: Khi ph ng th c start() đ c g i.ạ ươ ứ ượ ọ
• Tr ng thái running: M t Thread tr ng thái ready có quy n u tiên cao nh t sạ ộ ở ạ ề ư ấ ẽ
đ c chuy n sang tr ng thái này.ượ ể ạ
• Tr ng thái dead: Khi m t Thread ng ng ho c hoàn thành nhi m v c a nó.ạ ộ ư ặ ệ ụ ủ
Ngoài ra, m t thread running cũng có th b ch n (blocked) trong các thao tác vào ra.ộ ể ị ặ
Lúc này nó cũng không s d ng tài nguyên CPU.ử ụ
• Tr ng thái sleep: Khi Thread g i ph ng th c sleep. N u đang tr ng thái sleepạ ọ ươ ứ ế ở ạ
mà g i ph ng th c interrupt(), tread s thoát kh i tr ng thái sleep và chuy nọ ươ ứ ẽ ỏ ạ ể
sang tr ng thái ready.ạ
Sau đây là s đ tr ng thái c a m t thread.ơ ồ ạ ủ ộ
138
Khi m t thread đang ch y g i ph ng th c wait(), thread s r i vào m t tr ng thái waitộ ạ ọ ươ ứ ẽ ơ ộ ạ
đ đ i m t đ i t ng mà nó đã g i.ể ợ ộ ố ượ ọ
III. Các thu c tính c a threadộ ủ
III.1 Đ u tiên c a threadộ ư ủ
M i Thread có m t đ u tiên. M c đ nh thì thread th a k đ u tiên t thread chaỗ ộ ộ ư ặ ị ừ ế ộ ư ừ
c a nó- là thread đã g i nó. Ta có th tăng ho c gi m đ u tiên c a b t kỳ thread nào v iủ ọ ể ặ ả ộ ư ủ ấ ớ
ph ng th c setPriority() b ng m t giá tr n m gi a MIN_PRIORITY(1) và MAX_PRIORITYươ ứ ằ ộ ị ằ ữ
(10).
Trình t th c hi n c a các thread theo đ u tiên c a nó đ c minh h a nh sau:ừ ự ệ ủ ộ ư ủ ượ ọ ư
139
Các thread có đ u tiên càng cao thì kh năng th c hi n càng cao.ộ ư ả ự ệ
III.2 Nhóm thread
Các thread có th đ c đ a vào cùng m t nhóm đ có th đ ng th i làm vi c v i cể ượ ư ộ ể ể ồ ờ ệ ớ ả
nhóm thread này.
Khai báo m t nhóm Thread:ộ
String groupName = . . .;
ThreadGroup g = new ThreadGroup(groupName)
Sau đó, v i m i thread đ c t o ra ta dùng constructor có khai báo nhóm thread:ớ ỗ ượ ạ
Thread t = new Thread(g, threadName);
Đ ki m tra xem có thread nào trong nhóm g còn ho t đ ng không, ta dùng ph ngể ể ạ ộ ươ
th c:ứ
g. activeCount();
Đ ng t t t c các thread trong nhóm g ta g i:ể ắ ấ ả ọ
g.interrupt();
III.3 Qu n lý các ngo i l c a threadả ạ ệ ủ
Ph ng th c run() không th ném ra m t ngo i l đ c ki m soát mà b k t thúc b iươ ứ ể ộ ạ ệ ượ ể ị ế ở
m t ngo i l không ki m soát đ c m i khi có l i. Không có m nh đ catch nào đ c th cộ ạ ệ ể ượ ỗ ỗ ệ ề ượ ự
140
hi n mà thay vào đó, tr c khi thread b dead, ngo i l này s đ c g i cho m t b x lýệ ướ ị ạ ệ ẽ ượ ử ộ ộ ử
ngo i l không đ c ki m soát.ạ ệ ượ ể
B x lý này ph i thu c m t l p có cài đ t giao di nộ ử ả ộ ộ ớ ặ ệ
Thread.UncaughtExceptionHandler ch v i 1 ph ng th c:ỉ ớ ươ ứ
void uncaughtException(Thread t, Throwable e);
T phiên b n Java 1.5, ta có th cài b x lý ngo i l cho b t c thread nào b ngừ ả ể ộ ử ạ ệ ấ ứ ằ
ph ng th c: setUncaughtExceptionHandler(). Mgoaif ra ta có th cài b x lý ngo i l m cươ ứ ể ộ ử ạ ệ ặ
đ nh cho t t c các thread b ng cách g i ph ng th c setDefaultUncaughtExceptionHandlerị ấ ả ằ ọ ươ ứ
c a l p Thread.ủ ớ
N u không cài b x lý ngo i l cho m t thread thì m c đ nh là null. Tuy nhiên, cácế ộ ử ạ ệ ộ ặ ị
thread riêng l i ph thu c vào b x lý c a nhóm thread ch a nó. Khi này, ph ng th cạ ụ ộ ộ ử ủ ứ ươ ứ
uncaughtException s làm các vi c sau:ẽ ệ
1- N u nhóm thread có cài đ t uncaughtException thì ph ng th c đó đ c g i.ế ặ ươ ứ ượ ọ
2- Ng c l i, n u ph ng th c Thread.getDefaultExceptionHandler tr v m t b xượ ạ ế ươ ứ ả ề ộ ộ ử
lý không ph i là null thì b x lý này đ c g i.ả ộ ử ượ ọ
3- N u là null, n u Throwable là m t đ i t ng c a TheadDead, không có gì x y ra.ế ế ộ ố ượ ủ ả
4- N u không, tên c a thread và stack trace đ c g i t i System.err và đ a ra màn hình.ế ủ ượ ử ớ ư
IV. Đi u khi n các threadề ể
Sau khi đã kh i đ ng đ c m t thread r i, v n đ ti p theo s là đi u khi n thread.ở ộ ượ ộ ồ ấ ề ế ẽ ề ể
IV.1 Interrupt m t threadộ
Khi s d ng ph ng th c Thread.sleep(int) thì ch ng trình th ng ph i b t các ngo iử ụ ươ ứ ươ ườ ả ắ ạ
l đ x lý. Lý do là thread b d ng l i trong m t kho ng th i gian lâu và trong kho ng th iệ ể ử ị ừ ạ ộ ả ờ ả ờ
gian đó nó không th t đánh th c nó đ c. Tuy nhiên, n u m t thread c n ph i đ c đánhể ự ứ ượ ế ộ ầ ả ượ
th c s m h n, ta có th ng t nó dùng ph ng th c interrupt().ứ ớ ơ ể ắ ươ ứ
public class SleepyHead extends Thread
{
// Ph ng th c đ c ch y khi thread kh i đ ng l n đ uươ ứ ượ ạ ở ộ ầ ầ
public void run()
{
System.out.println ("Thread đang ng . Hãy đánh th c nó");ủ ứ
try
{
// Ng trong 8 ti ngủ ế
Thread.sleep( 1000 * 60 * 60 * 8 );
System.out.println ("Đó là m t gi c ng tr a");ộ ấ ủ ư
}
catch (InterruptedException ie)
{
System.err.println ("Ch m i đ c h n 5 phút thôi....");ỉ ớ ượ ơ
}
}
// Ph ng th c main t o và b t đ u threadươ ứ ạ ắ ầ
public static void main(String args[]) throws
java.io.IOException
141
{
// T o m t threadạ ộ
Thread sleepy = new SleepyHead();
// b t đ u threadắ ầ
sleepy.start();
// Nh c ng i dùng đ d ng threadắ ườ ể ừ
System.out.println ("Nh n Enter đ ng ng thread");ấ ể ư
System.in.read();
// Ng t threadắ
sleepy.interrupt();
}}
Cách th c hi n đây là g i m t thông đi p t m t thread khác đ đánh th c m tự ệ ở ử ộ ệ ừ ộ ể ứ ộ
thread đang ng . đây, thread chính- hàm main- s đ i cho ng i dùng n enter, sau đó g iủ Ở ẽ ợ ườ ấ ử
m t thông đi p ng t t i thread đang ng .ộ ệ ắ ớ ủ
IV.2 D ng m t threadừ ộ
Đôi khi ta mu n m t thread d ng l i tr c khi nhi m v c a nó hoàn thành. M tố ộ ừ ạ ướ ệ ụ ủ ộ
thread (g i là thread đi u khi n) có th g i m t thông đi p d ng t i m t thread khác b ngọ ề ể ể ử ộ ệ ừ ớ ộ ằ
vi c g i ph ng th c Thread.stop(). Đi u này yêu c u thread đi u khi n ph i gi m t thamệ ọ ươ ứ ề ầ ề ể ả ữ ộ
chi u t i thread mu n d ng.ế ớ ố ừ
public class StopMe extends Thread
{
// Ph ng th c đ c th c hi n khi thread kh i đ ng l n đ uươ ứ ượ ự ệ ở ộ ầ ầ
public void run()
{
int count = 1;
System.out.println ("Thread đ m!");ế
for (;;)
{
// In ra bi n count và tăng giá tr cho nóế ị
System.out.print (count++ + " ");
// Ng n a giâyủ ử
try { Thread.sleep(500); } catch
(InterruptedException ie) {}
}}
// ph ng th c mainươ ứ
public static void main(String args[]) throws java.io.IOException
{
// T o và b t đ u threadạ ắ ầ
Thread counter = new StopMe();
counter.start();
// Nh c ng i dùngắ ườ
System.out.println ("Nh n Enter đ d ng đ m");ấ ể ừ ế
System.in.read();
// D ng threadừ
counter.stop();
142
}}
IV.3 T m d ng và ph c h i m t threadạ ừ ụ ồ ộ
Các ph ng th c suspend() dùng đ t m d ng m t thread trong khi resume() dùng đươ ứ ể ạ ừ ộ ể
ti p t c m t thread đã b suspend. Tuy nhiên s d ng các thread này r t hay gây ra tình tr ngế ụ ộ ị ử ụ ấ ạ
deadlock do thread b suspend đang chi m gi m t tài nguyên và không gi i phóng trong khiị ế ữ ộ ả
nhi u thread khác có th đang đ i s d ng tài nguyên đó.ề ể ợ ử ụ
IV.4 Gi i phóng th i gian cho CPUả ờ
Khi m t thread r i vào tr ng thái đ i m t s ki n x y ra ho c đi vào m t vùng mãộ ơ ạ ợ ộ ự ệ ả ặ ộ
l nh mà n u gi i phóng th i gian cho CPU s nâng cao hi u qu c a h th ng. Trong tr ngệ ế ả ờ ẽ ệ ả ủ ệ ố ườ
h p này, thread nên gi i phóng th i gian h th ng h n là dùng sleep() đ ngh trong th i gianợ ả ờ ệ ố ơ ể ỉ ờ
dài. Đ làm đi u này ta dùng ph ng th c static yield() c a Thread đ gi i phóng th i gianể ề ươ ứ ủ ể ả ờ
CPU cho thread hi n th i. Ta không th gi i phóng th i gian CPU c a b t kỳ thread nào màệ ờ ể ả ờ ủ ấ
ch đ i v i thread hi n th i.ỉ ố ớ ệ ờ
IV.5 Đ i m t thread k t thúc công vi cợ ộ ế ệ
Đôi khi ta c n đ i cho m t thread k t thúc m t công vi c nào đó nh g i m t ph ngầ ợ ộ ế ộ ệ ư ọ ộ ươ
th c hay đ c m t thu c tính thành ph n,…Ta dùng ph ng th c isAlive() đ xác đ nh threadứ ọ ộ ộ ầ ươ ứ ể ị
còn ch y không. Tuy nhiên, n u th ng xuyên dùng ph ng th c này đ ki m tra sau đó dùngạ ế ườ ươ ứ ể ể
sleep() ho c yield() thì hi u qu s d ng CPU s r t th p. M t cách hi u qu là g i ph ngặ ệ ả ử ụ ẽ ấ ấ ộ ệ ả ọ ươ
th c joint() đ đ i m t thread k t thúc công vi c.ứ ể ợ ộ ế ệ
public class WaitForDeath extends Thread
{
// Ph ng th c run()ươ ứ
public void run()
{
System.out.println ("thread chu n b ngh ....");ẩ ị ỉ
// Ngh trong 5 giâyỉ
try
{
Thread.sleep(5000);
}
catch (InterruptedException ie) {}
}
// ph ng th c mainươ ứ
public static void main(String args[]) throws
java.lang.InterruptedException
{
// T o threadạ
Thread dying = new WaitForDeath();
dying.start();
// Nh c userắ
System.out.println ("Đ i cho thread k t thúc");ợ ế
dying.join();
System.out.println ("Thread đã d ng");ừ }}
143
V. Đ ng b threadồ ộ
Trong h u h t các ch ng trình đa lu ng, các thread có th c n ph i truy c p đ n cùngầ ế ươ ồ ể ầ ả ậ ế
m t đ i t ng. Đi u gì x y ra n u c hai thread cùng truy c p đ n đ i t ng và làm thay đ iộ ố ượ ề ả ế ả ậ ế ố ượ ổ
thu c tính đ i t ng. K t qu có th là các thread b nh h ng l n nhau và không đ t đ cộ ố ượ ế ả ể ị ả ưở ẫ ạ ượ
k t qu mong mu n. Tình tr ng này g i là “đua tranh”.ế ả ố ạ ọ
V.1 Tình tr ng “đua tranh”ạ
Trong ph n ti p theo, chúng ta mô ph ng m t ngân hàng có r t nhi u tài kho n kháchầ ế ỏ ộ ấ ề ả
hàng. Chúng ta th thi t k m t ch ng trình đ chuy n ti n ng u nhiên gi a các tài kho n.ử ế ế ộ ươ ể ể ề ẫ ữ ả
M i tài kho n có m t thread riêng. M i giao d ch th c hi n vi c chuy n ti n t account sangỗ ả ộ ỗ ị ự ệ ệ ể ề ừ
m t account ng u nhiên khác.ộ ẫ
Ta có m t class Bank v i ph ng th c transfer đ chuy n ti n. N u account chuy nộ ớ ươ ứ ể ể ề ế ể
không đ ti n, giao d ch k t thúc ngay. ủ ề ị ế
public void transfer(int from, int to, double amount)
{
System.out.print(Thread.currentThread());
accounts[from] -= amount;
System.out.printf(" %10.2f from %d to %d", amount, from, to);
accounts[to] += amount;
System.out.printf(" S d : %10.2f%n", getTotalBalance());ố ư
}
Sau đây là đo n code cho class transferRunnable:ạ
class TransferRunnable implements Runnable
{
. . .
public void run()
{
try
{
int toAccount = (int) (bank.size() * Math.random());
double amount = maxAmount * Math.random();
bank.transfer(fromAccount, toAccount, amount);
Thread.sleep((int) (DELAY * Math.random()));
}
catch(InterruptedException e) {}
}
}
Khi ch ng trình ch y, ta không bi t đ c trong m i tài kho n còn bao nhiêu ti nươ ạ ế ượ ỗ ả ề
nh ng t ng s ti n c a t t c các tài kho n là không đ i. Ch ng trình trên ch y và khôngư ổ ố ề ủ ấ ả ả ổ ươ ạ
bao gi d ng l i, ta ph i n Ctrl + C đ d ng nó.ờ ừ ạ ả ấ ể ừ
Tuy nhiên, trong m t s tình hu ng ch ng trình trên có th gây l i và in ra t ng sộ ố ố ươ ể ỗ ổ ố
ti n khác nhau, đó là khi có nhi u h n m t tài kho n cùng chuy n ti n đ n m t tài kho nề ề ơ ộ ả ể ề ế ộ ả
khác, t c là cùng th c hi n câu l nh:ứ ự ệ ệ
account[to] += amount;
144
Gi s đây là m t hành vi đ n v (atomic- hành vi ch chi m m t chu kỳ th c hi n l nhả ử ộ ơ ị ỉ ế ộ ự ệ ệ
c a CPU), khi đó m i thread s th c hi n phép tính này m t cách tu n t mà không gây nhủ ỗ ẽ ự ệ ộ ầ ự ả
h ng vì trong m t th i đi m, CPU cũng ch ph c v đ c cho m t thread.ưở ộ ờ ể ỉ ụ ụ ượ ộ
Tuy nhiên, phép tính này l i không ph i là atomic, công vi c có th ph i làm là:ạ ả ệ ể ả
1- Load giá tr account[to] vào thanh ghiị
2- C ng v i accountộ ớ
3- Load k t qu ng c tr l i cho account[to]ế ả ượ ả ạ
Gi s có 2 thread là thread_1 và thread_2 cùng th c hi n đ n dòng l nh này. Thread_1ả ử ự ệ ế ệ
th c hi n xong b c 1 và 2 thì b ng t, sau đó thread_2 s th c hi n câu l nh trên v i đ y đự ệ ướ ị ắ ẽ ự ệ ệ ớ ầ ủ
3 b c t c là account[to] đã b thay đ i giá tr . Ti p theo, thread_1 th c d y và làm ti p b cướ ứ ị ổ ị ế ứ ậ ế ướ
3, account[to] lúc này đã ghi đè giá tr do thread_2 c p nh t. Đi u này d n t i vi c t ng s ti nị ậ ậ ề ẫ ớ ệ ổ ố ề
b thay đ i, ph n ti n do thread_2 chuy n cho account[to] đã b m t.ị ổ ầ ề ể ị ấ
V.2 Khóa đ i t ngố ượ
Trong ví d trên, n u ta đ m b o r ng ph ng th c transfer() đ c th c hi n thànhụ ế ả ả ằ ươ ứ ượ ự ệ
công tr c khi thread b ng t thì s không có v n đ gì x y ra. Có nghĩa là, trong m t th iướ ị ắ ẽ ấ ề ả ộ ờ
đi m s ch có m t thread đ c truy c p vào m t đo n mã l nh nào đó.ể ẽ ỉ ộ ượ ậ ộ ạ ệ
T phiên b n Java 5.0 có h tr hai c ch đ b o v m t kh i l nh kh i s truy c pừ ả ỗ ợ ơ ế ể ả ệ ộ ố ệ ỏ ự ậ
đ ng th i. Các phiên b n tr c c a Java s d ng t khóa synchronized, Java 5.0 gi i thi uồ ờ ả ướ ủ ử ụ ừ ớ ệ
thêm l p ReentrantLock cho m c đích này.ớ ụ
C u trúc đo n l nh căn b n đ s d ng c ch này là:ấ ạ ệ ả ể ử ụ ơ ế
myLock.lock(); // đ i t ng ReentrantLock ố ượ
try
{
//Đo n l nh c n b o vạ ệ ầ ả ệ
}
finally
{
myLock.unlock(); // đ m b o khóa đ c m k c khi exception x y ra ả ả ượ ở ể ả ả
}
Đo n l nh này đ m b o r ng ch có m t thread t i m t th i đi m có th đi vào vùngạ ệ ả ả ằ ỉ ộ ạ ộ ờ ể ể
đ c b o v . Khi m t thread đ u tiên đã g i lock thì không m t thread nào sau đó có th v tượ ả ệ ộ ầ ọ ộ ể ượ
qua l nh lock().ệ
Bây gi chúng ta s khóa ph ng th c transfer() trong l p Bank:ờ ẽ ươ ứ ớ
public class Bank
{
public void transfer(int from, int to, int amount)
{
bankLock.lock();
try
{
if (accounts[from] < amount) return;
System.out.print(Thread.currentThread());
accounts[from] -= amount;
System.out.printf(" %10.2f from %d to %d", amount, from, to);
accounts[to] += amount;
System.out.printf(" Total Balance: %10.2f%n", getTotalBalance());
145
}
finally
{
bankLock.unlock();
}
}
. . .
private Lock bankLock = new ReentrantLock(); // ReentrantLock là m t l p cài đ tộ ớ ặ
giao di n lock.ệ
}
V.3 Đ i t ng đi u ki nố ượ ề ệ
Trong tr ng h p thread đi vào vùng b o v , nó c n hoàn thành công vi c đ có thườ ợ ả ệ ầ ệ ể ể
m khóa cho các thread khác đi vào. Tuy nhiên, n u trong đó công vi c chính c n th c hi n bở ế ệ ầ ự ệ ị
gi i h n b i m t đi u ki n nào đó, ch ng h n đây, vi c g i transfer() đ chuy n ti n chớ ạ ở ộ ề ệ ẳ ạ ở ệ ọ ể ể ề ỉ
đ c th c hi n khi s ti n c a account g i l n h n s ti n đ c g i:ượ ự ệ ố ề ủ ử ớ ơ ố ề ượ ử
if (bank.getBalance(from) >= amount)
bank.transfer(from, to, amount);
Khi có đi u ki n này, m t thread có th không th a mãn và nó không th c hi n vi cề ệ ộ ể ỏ ự ệ ệ
chuy n ti n, t c là công vi c c a nó là không h u ích. Đ n đây, ta có th nghĩ ra m t gi iể ề ứ ệ ủ ữ ế ể ộ ả
pháp là đ thread đ i cho đ n khi nó có đ ti n đ chuy n:ể ợ ế ủ ề ể ể
public void transfer(int from, int to, int amount)
{
bankLock.lock();
try
{
while (accounts[from] < amount) // Đ i cho đ n khi tài kho n c a nó có đ ti nợ ế ả ủ ủ ề
{
// đ iợ
. . .
}
// Chuy n ti nể ề
. . .
}
finally
{
bankLock.unlock();
}
}
Vi c đ i đây s k t thúc khi m t thread khác chuy n ti n vào cho nó. Tuy nhiên taệ ợ ở ẽ ế ộ ể ề
th y r ng vùng ch a l nh chuy n ti n l i đang b khóa b i chính thread này nên các threadấ ằ ứ ệ ể ề ạ ị ở
khác không th chuy n ti n đ c. K t qu là thread này không bao gi thoát kh i tình tr ngể ể ề ượ ế ả ờ ỏ ạ
đ i, ch ng trình r i vào deadlock.ợ ươ ơ
Đây là tình hu ng mà ta ph i s d ng đ i t ng đi u ki n:ố ả ử ụ ố ượ ề ệ
class Bank
{
public Bank()
146
{
. . .
sufficientFunds = bankLock.newCondition();
}
. . .
private Condition sufficientFunds;
}
N u ph ng th c transfer() ki m tra và th y r ng nó ch a đ ti n đ chuy n thì nó sế ươ ứ ể ấ ằ ư ủ ề ể ể ẽ
g i:ọ
sufficientFunds.await();Lúc này nó s n m ch thread khác chuy n ti n.ẽ ằ ờ ể ề
Có m t s khác nhau căn b n gi a m t thread đang đ i đ khóa (g i ph ng th cộ ự ả ữ ộ ợ ể ọ ươ ứ
lock() đ đi vào vùng b o v ) và thread g i ph ng th c await(). Nó s không th m khóaể ả ệ ọ ươ ứ ẽ ể ở
khi đang n m trong vùng khóa cho đ n khi m t thread khác g i signalAll(). M t thread th cằ ế ộ ọ ộ ự
hi n xong vi c chuy n ti n, nó nên g i: sufficientFunds.signalAll() đ m khóa cho các threadệ ệ ể ề ọ ể ở
đang n m đ i th a mãn đi u ki n đ ti n. M t khi thread đã thoát kh i tình tr ng đ i doằ ợ ỏ ề ệ ủ ề ộ ỏ ạ ợ
await() gây ra, nó s đ c ch y ti p và c g ng đi vào vùng khóa và b t đ u t v trí mà nóẽ ượ ạ ế ố ắ ắ ầ ừ ị
ch đ i tr c đó - v trí g i ph ng th c await() và ki m tra l i đi u ki n.ờ ợ ướ ị ọ ươ ứ ể ạ ề ệ
M t ph ng th c await() nên đ c g i trong m t vòng l p đ i:ộ ươ ứ ượ ọ ộ ặ ợ
while (!(đ ti n))ủ ề
condition.await();
N u không có thread nào g i signalAll() thì thread đang đ i không có cách nào ch yế ử ợ ạ
ti p đ c. N u t t c các thread khác đ u đang b ch n, thread g i await() không gi phóngế ượ ế ấ ả ề ị ặ ọ ả
tình tr ng này cho m t thread nào đó thì b n thân nó cũng b ch n, ch ng trình s b treo.ạ ộ ả ị ặ ươ ẽ ị
V n đ là khi nào thì g i signalAll()? Nguyên t c chung là khi m t thread hoàn thànhấ ề ọ ắ ộ
vi c thay đ i tr ng thái đ i t ng thì nó nên g i signalAll(). đây, sau khi c ng ti n vào choệ ổ ạ ố ượ ọ Ở ộ ề
tài kho n nh n và thì signalAll() s đ c g i. Vi c g i này s giúp các thread cũng đang trongả ậ ẽ ượ ọ ệ ọ ẽ
tình tr ng ch đ i này không b ch n n a và ti p t c công vi c v i m t giá tr tài kho n cóạ ờ ợ ị ặ ữ ế ụ ệ ớ ộ ị ả
th đã b thay đ i.ể ị ổ
public void transfer(int from, int to, int amount)
{
bankLock.lock();
try
{
while (accounts[from] < amount)
sufficientFunds.await();
// Chuy n ti nể ề
. . .
sufficientFunds.signalAll();
}
finally
{
bankLock.unlock();
}
}
Chú ý là vi c g i signalAll() không ph i là kích ho t thread b ch n ngay l p t c. Nóệ ọ ả ạ ị ặ ậ ứ
ch gi i phóng tình tr ng b ch n c a các thread khác cho đ n khi nó k t thúc đo n ch ngỉ ả ạ ị ặ ủ ế ế ạ ươ
trình đ c b o v . M t ph ng th c khác là sign() ch trao khóa cho m t thread xác đ nh thayượ ả ệ ộ ươ ứ ỉ ộ ị
147
vì t t c . M t thread ch có th g i các ph ng th c signalAll(), sign() và await() trong vùngấ ả ộ ỉ ể ọ ươ ứ
đ c b o v .ượ ả ệ
Chúng ta có th k t thúc ph n này b ng m t câu chuy n minh h a: Có 10 ng i cùngể ế ầ ằ ộ ệ ọ ườ
đ n ngân hàng đ chuy n ti n cho nhau, m i ng i chuy n cho m t ng i khác trong s 9ế ể ể ề ỗ ườ ể ộ ườ ố
ng i còn l i. M i th i đi m ngân hàng ch chuy n ti n cho m t ng i, ng i đ c g i ti nườ ạ ỗ ờ ể ỉ ể ề ộ ườ ườ ượ ử ề
s đ c vào trong ngân hàng và gi khóa c ng, 9 ng i khác ph i ch ngoài c ng. N u ch ngẽ ượ ữ ổ ườ ả ờ ổ ế ẳ
may ng i đang th c hi n chuy n s ti n l n h n anh ta có, anh ta s đ i trong ngân hàngườ ự ệ ể ố ề ớ ơ ẽ ợ ở
(g i await()) và ném khóa ra ngoài c ng cho t t c 9 ng i kia. M t trong s 9 ng i ngoàiọ ổ ấ ả ườ ộ ố ườ
c ng s đ c đi vào trong ngân hàng, th c hi n vi c chuy n ti n. Sau khi chuy n xong, anh taổ ẽ ượ ự ệ ệ ể ề ể
thông báo cho t t c các anh khác đang ph i đ i trong ngân hàng là mình v a chuy n ti n (g iấ ả ả ợ ừ ể ề ọ
signalAll()) r i đi ra ngoài, sau đó nh ng ng i đang đ i cũng quay ra c ng đ đ i đ n l tồ ữ ườ ợ ổ ể ợ ế ượ
vào.
Bài t pậ
1. Vi t m t ch ng trình t o m t thread th c hi n vi c gi i m t ph ng trình b c 2ế ộ ươ ạ ộ ự ệ ệ ả ộ ươ ậ
v i các h s cho tr c.ớ ệ ố ướ
2. Vi t ch ng trình song song v i 10 thread đ c ng 10000 s t nhiên liên ti p t 1ế ươ ớ ể ộ ố ự ế ừ
đ n 10000.ế
148
Ph l c A. Các t khóa c a Javaụ ụ ừ ủ
T khóaừ Ý nghĩa
abstract M t l p ho c ph ng th c tr u t ngộ ớ ặ ươ ứ ừ ượ
assert Đ c s d ng đ đ nh v l i n i b ch ng trìnhượ ử ụ ể ị ị ỗ ộ ộ ươ
boolean Ki u booleanể
break Thoát kh i l nh switch ho c các vòng l pỏ ệ ặ ặ
byte S nguyên 1 byteố
case M t l a chon c a switchộ ự ủ
catch M t m nh đ c a kh i Try đ b t m t ngo i lộ ệ ề ủ ố ể ắ ộ ạ ệ
char Ki u ký t Unicodeể ự
class Đ nh nghĩa m t classị ộ
const Không đ c s d ngượ ử ụ
continue Ti p t c t i v trí cu i vòng l p hi n th iế ụ ạ ị ố ặ ệ ờ
default M nh đ m c đ nh c a switchệ ề ặ ị ủ
do Ph n trên c a vòng l p do/while ầ ủ ặ
double Ki u s th c floating-number 8 byteể ố ự
else M nh đ else c a m t l nh ifệ ề ủ ộ ệ
extends Xác đ nh l p cha c a m t l pị ớ ủ ộ ớ
final M t h ng s , ho c m t l p hay ph ng th c không th b khai báo ch ng.ộ ằ ố ặ ộ ớ ươ ứ ể ị ố
finally M t ph n c a kh i try mà luôn đ c th c hi nộ ầ ủ ố ượ ự ệ
float S th c 4 byteố ự
for M t ki u vòng l pộ ể ặ
goto Không s d ngử ụ
if M t l nh đi u khi n r nhánhộ ệ ề ể ẽ
implements Ch ra các interfaces mà l p s cài đ t.ỉ ớ ẽ ặ
import Nh p m t packageậ ộ
instanceof Ki m tra xem đ i t ng có ph i là bi u hi n c a m t l pể ố ượ ả ể ệ ủ ộ ớ
int S nguyên 4 byteố
interface M t ki u tr u t ng v i các ph ng th c đ c cài đ t t i các classộ ể ừ ượ ớ ươ ứ ượ ặ ạ
long Sô nguyên 8 byte
149
T khóaừ Ý nghĩa
Native a method implemented by the host system
new C p phát vùng nh cho m t đ i t ng ho c m ng m iấ ớ ộ ố ượ ặ ả ớ
null M t tham chi u nullộ ế
package M t gói các l pộ ớ
private a feature that is accessible only by methods of this class
protected a feature that is accessible only by methods of this class, its children, and other
classes in the same package
public a feature that is accessible by methods of all classes
return returns from a method
short the 16-bit integer type
static a feature that is unique to its class, not to objects of its class
strictfp Use strict rules for floating-point computations
super the superclass object or constructor
switch a selection statement
synchronized a method or code block that is atomic to a thread
this the implicit argument of a method, or a constructor of this class
throw throws an exception
tHRows the exceptions that a method can throw
transient marks data that should not be persistent
try a block of code that traps exceptions
void denotes a method that returns no value
volatile ensures that a field is coherently accessed by multiple threads
while a loop
Ph l c B M t s hàm hay s d ngụ ụ ộ ố ử ụ
a) Hàm toán h c, l p java.lang.Math; {java.math.*;}ọ ớ
1. abs(number x): l y |x|, x có th là các ki u long, int, float, double.ấ ể ể
2. acos(double x) = arccos(x). x t 0.0 ... PIừ
3. asin(double x) = arcsin(x). x t -PI/2 ... PI/2ừ
4. atan(double x) = arctag(x).
5. ceil(double x): làm c n trên ho c c n d i c a s x.ậ ặ ậ ướ ủ ố
6. cos(double x) = cos(x). x là radian.
7. exp(double x) = ex.
8. log(double x) = Ln(x).
150
9. max(number x, number y) = max{x, y}, trong đó x, y có th là ki u int, float,ể ể
double, long.
10. min(number x, number y) = min{x, y}, trong đó x, y có th là ki u int, float,ể ể
double, long.
11. pow(double x, double y) = xy.
12. random(): cho m t s ng u nhiên trong [0.0, 1.0].ộ ố ẫ
13. round(number x): làm tròn s x, n u x là ki u double thì thành ki u long, n u xố ế ể ể ế
là ki u float thì thành ki u int.ể ể
14. sin(double x) = sin(x).
15. sqrt(double x) =
16. tan(double x) = tg(x).
Khi s d ng ta ph i dùng Math.tên_hàm.ử ụ ả
b) L p String, khai báo java.lang.String;ớ
1. String() : Kh i đ ng m t đ i t ng chu i.ở ộ ộ ố ượ ỗ
2. String(String s) : Kh i đ ng m t chu i b ng chu i s.ở ộ ộ ỗ ằ ỗ
3. length() : tr v giá tr int là đ dài m t chu i.ả ề ị ộ ộ ỗ
4. charAt(int i): tr v m t ký t th sau i.ả ề ộ ự ứ
5. indexOf(int ch): tr v v trí tr c c a ký t ch đ u tiên tìm th y.ả ề ị ướ ủ ự ầ ấ
6. concat(String str): n i thêm chu i str vào sau.ố ỗ
7. toLowerCase(): thay đ i chu i thành ch th ng.ổ ỗ ữ ườ
8. toUpperCase(): chuy n đ i chu i thành ch HOA.ể ổ ỗ ữ
L p Date khai báo java.util.Date;ớ
1. Date(): cho th , tháng, ngày, gi , năm.ứ ờ
2. getDate(): tr v giá tr c a ngày trong tháng.ả ề ị ủ
3. getDay(): tr v giá tr int là th trong tu n, 0 = CN, 1 = mon, ..., 6 = Sat.ả ề ị ứ ầ
4. getMonth(): tr v giá tr int là tháng trong năm (0..11).ả ề ị
5. getYear(): tr v giá tr int là năm. L y m c là 1900, năm th c = date.getYear()ả ề ị ấ ố ự
+1900.
6. getTime(): tr v là m t s đ c tính theo giây đ ng h .ả ề ộ ố ượ ồ ồ
7. getHours(): tr v giá tr int ch gi trong ngày.ả ề ị ỉ ờ
8. getMinutes(): tr v giá tr int ch phút trong gi .ả ề ị ỉ ờ
9. getSeconds(): tr v giá tr int ch giây đ ng h trong phút.ả ề ị ỉ ồ ồ
10. setDate(int date) đ t l i ngày trong bi n. date l y giá tr t 1..31ặ ạ ế ấ ị ừ
11. setMonth(int month): thay đ i giá tr tháng trong bi n date. month có giá tr 0..11.ổ ị ế ị
12. setYear(int year): thay đ i giá tr năm trong bi n date. (year + 1900).ổ ị ế
13. setHours(int hour): thay đ i giá tr gi trong bi n date.ổ ị ờ ế
14. setMinutes(int i): thay đ i giá tr phút trong bi n date.ổ ị ế
15. setSeconds(int i): thay đ i giá tr giây trong bi n date.ổ ị ế
Tài li u tham kh oệ ả
[1] Deitel & Associates (2001), “Java, How to program”, fourth edition.
[2] Cay S. Horstmann, Gary Cornell (2004), “Core Java™ 2”, volume 1,2, Prentice Hall PTR
[3] David Reilly, Michael Reilly (2002), “Network Programming and Distributed Computing”,
Addison Wesley
151
Các file đính kèm theo tài liệu này:
- Lịch sử hình thành và phát triển ngôn ngữ lập trình Java.pdf