Commit 6b38253c by Adam Gerber

merged in lab10g

parent f139202f
Showing with 3876 additions and 336 deletions
package lec09.glab.debugging;
/**
* Created with IntelliJ IDEA.
* User: ag
* Date: 11/18/13
* Time: 11:05 AM
* To change this template use File | Settings | File Templates.
*/
public class Driver {
public static void main(String[] args) {
for (int nC = 0; nC <20 ; nC++) {
System.out.print("hello");
doSomething(nC);
}
}
private static void doSomething(int nNum){
System.out.println(doSomeMore("goodbybe") + nNum);
}
private static String doSomeMore(String str){
return "A" + str;
}
}
package lec09.glab.etc;
/**
* Created with IntelliJ IDEA.
* User: ag
* Date: 11/18/13
* Time: 11:45 AM
* To change this template use File | Settings | File Templates.
*/
public class FibDriver {
public static void main(String[] args) {
System.out.println(fib(4));
System.out.println(mystery(1,5));
}
private static int fib(int n) { // assumes n >= 0
if (n <= 1)
return n;
else
return (fib(n - 1) + fib(n - 2));
}
private static int mystery (int n, int m) {
if (n == 0)
return 0;
if (n == 1)
return m;
return m + mystery(n - 1, m);
}
}
package lec09.glab.notepad;
import javax.swing.*;
import java.awt.*;
import java.awt.datatransfer.*;
import java.io.*;
public class ClipboardAndFileUtil {
private static Clipboard clp = Toolkit.getDefaultToolkit().getSystemClipboard();
public static void copy(String strCopy) {
StringSelection sel = new StringSelection(strCopy);
clp.setContents(sel, null);
}
//http://www.javapractices.com/topic/TopicAction.do?Id=82
public static String paste() {
String result = "";
Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
//odd: the Object param of getContents is not currently used
Transferable contents = clipboard.getContents(null);
boolean hasTransferableText =
(contents != null) &&
contents.isDataFlavorSupported(DataFlavor.stringFlavor);
if (hasTransferableText) {
try {
result = (String) contents.getTransferData(DataFlavor.stringFlavor);
} catch (UnsupportedFlavorException | IOException ex) {
System.out.println(ex);
ex.printStackTrace();
}
}
return result;
}
//http://stackoverflow.com/questions/14589386/how-to-save-file-using-jfilechooser-in-java
public static void save(String strContent) {
//String sb = "TEST CONTENT";
JFileChooser chooser = new JFileChooser();
//http://stackoverflow.com/questions/15954770/starting-a-jfilechooser-at-a-specified-directory-and-only-showing-files-of-a-spe
chooser.setFileFilter(new javax.swing.filechooser.FileFilter() {
@Override
public boolean accept(File f) {
if (f.isDirectory()) {
return true;
} else {
return false;
}
}
@Override
public String getDescription() {
return "*.txt";
}
});
//chooser.setCurrentDirectory(new File("/home/me/Documents"));
int nUserFeedback = chooser.showSaveDialog(null);
//BufferedWriter out
if (nUserFeedback == JFileChooser.APPROVE_OPTION) {
//try with resources Java7
try (FileWriter fstream = new FileWriter(chooser.getSelectedFile() + ".txt");
BufferedWriter out = new BufferedWriter(fstream)) {
out.write(strContent);
} catch (IOException e) {
e.printStackTrace();
}
}
}
public static String open() {
StringBuilder stringBuilder = new StringBuilder();
JFileChooser chooser = new JFileChooser();
//http://stackoverflow.com/questions/15954770/starting-a-jfilechooser-at-a-specified-directory-and-only-showing-files-of-a-spe
chooser.setFileFilter(new javax.swing.filechooser.FileFilter() {
@Override
public boolean accept(File f) {
if (f.isFile()) {
return true;
} else {
return false;
}
}
@Override
public String getDescription() {
return "*.txt";
}
});
int nUserFeedback = chooser.showOpenDialog(null);
if (nUserFeedback == JFileChooser.APPROVE_OPTION) {
//try with resources Java7
File file = chooser.getSelectedFile();
try(BufferedReader reader = new BufferedReader(new FileReader(file)))
{
String lineFromFile = "";
while((lineFromFile = reader.readLine()) != null){
stringBuilder.append(lineFromFile);
}
}catch(IOException exception){
System.out.println("Error while reading file");
}
}
return stringBuilder.toString();
}
}
<?xml version="1.0" encoding="UTF-8"?>
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="lec09.glab.notepad.GoodNotepad">
<grid id="27dc6" binding="mPanel" layout-manager="GridLayoutManager" row-count="1" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<xy x="20" y="20" width="500" height="400"/>
</constraints>
<properties/>
<border type="none"/>
<children>
<scrollpane id="f8bb6" binding="mScrollPane">
<constraints>
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="7" hsize-policy="7" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
<border type="none"/>
<children>
<component id="905cd" class="javax.swing.JTextArea" binding="mTextArea">
<constraints/>
<properties/>
</component>
</children>
</scrollpane>
</children>
</grid>
</form>
package lec09.glab.notepad;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.GregorianCalendar;
/**
* Created with IntelliJ IDEA.
* User: ag
* Date: 11/3/13
* Time: 6:29 PM
* To change this template use File | Settings | File Templates.
*/
public class GoodNotepad {
private JPanel mPanel;
private JTextArea mTextArea;
private JScrollPane mScrollPane;
private JMenuBar mMenuBar;
private JMenu mMenuFile;
private JMenu mMenuEdit;
private JMenu mMenuHelp;
private JMenu mMenuInsert;
private JMenuItem mMenuItemNew;
private JMenuItem mMenuItemOpen;
private JMenuItem mMenuItemSave;
private JMenuItem mMenuItemExit;
private JMenuItem mMenuItemCut;
private JMenuItem mMenuItemCopy;
private JMenuItem mMenuItemPaste;
private JMenuItem mMenuItemSelectAll;
private JMenuItem mMenuItemTime;
private JMenuItem mMenuItemDate;
private JMenuItem mMenuItemAbout;
private static JFrame sFrame;
public static void main(String[] args) {
sFrame = new JFrame("Good-Notepad");
sFrame.setContentPane(new GoodNotepad().mPanel);
sFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
sFrame.pack();
sFrame.setSize(600, 600);
sFrame.setVisible(true);
}
public GoodNotepad() {
//init
mTextArea.setLineWrap(true);
mTextArea.setWrapStyleWord(true);
mTextArea.setBackground(Color.GRAY);
mTextArea.setEditable(false);
mMenuBar = new JMenuBar();
//we will need access to the frame as a member so that we can ad the menu-bar
//refactor/extract/field
sFrame.setJMenuBar(mMenuBar);
//File menu
mMenuFile = new JMenu("File");
mMenuBar.add(mMenuFile);
mMenuItemNew = new JMenuItem("New");
mMenuFile.add(mMenuItemNew);
mMenuItemNew.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
mTextArea.setBackground(Color.WHITE);
mTextArea.setEditable(true);
}
});
mMenuItemOpen = new JMenuItem("Open");
mMenuFile.add(mMenuItemOpen);
mMenuItemOpen.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
mTextArea.setText(ClipboardAndFileUtil.open());
}
});
mMenuItemSave = new JMenuItem("Save");
mMenuFile.add(mMenuItemSave);
mMenuItemSave.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
ClipboardAndFileUtil.save(mTextArea.getText());
}
});
mMenuItemExit = new JMenuItem("Exit");
mMenuFile.add(mMenuItemExit);
mMenuItemExit.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
System.exit(0);
}
});
//Edit menu
mMenuEdit = new JMenu("Edit");
mMenuBar.add(mMenuEdit);
mMenuItemCut = new JMenuItem("Cut");
mMenuEdit.add(mMenuItemCut);
mMenuItemCut.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
ClipboardAndFileUtil.copy(mTextArea.getSelectedText());
mTextArea.replaceSelection("");
}
});
mMenuItemCopy = new JMenuItem("Copy");
mMenuEdit.add(mMenuItemCopy);
mMenuItemCopy.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
ClipboardAndFileUtil.copy(mTextArea.getSelectedText());
}
});
mMenuItemPaste = new JMenuItem("Paste");
mMenuEdit.add(mMenuItemPaste);
mMenuItemPaste.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
mTextArea.insert(ClipboardAndFileUtil.paste(), mTextArea.getSelectionStart());
}
});
mMenuItemSelectAll = new JMenuItem("Select All");
mMenuEdit.add(mMenuItemSelectAll);
mMenuItemSelectAll.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
mTextArea.selectAll();
}
});
//submenu of insert
mMenuInsert = new JMenu("Insert");
mMenuEdit.add(mMenuInsert);
mMenuItemDate = new JMenuItem("Date");
mMenuInsert.add(mMenuItemDate);
mMenuItemDate.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
mTextArea.insert(new GregorianCalendar().getTime().toString().substring(0, 10), mTextArea.getSelectionStart());
}
});
mMenuItemTime = new JMenuItem("Time");
mMenuInsert.add(mMenuItemTime);
mMenuItemTime.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
mTextArea.insert(new GregorianCalendar().getTime().toString().substring(11), mTextArea.getSelectionStart());
}
});
//Help Menu
mMenuHelp = new JMenu("Help");
mMenuBar.add(mMenuHelp);
mMenuItemAbout = new JMenuItem("About");
mMenuHelp.add(mMenuItemAbout);
mMenuItemAbout.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
JOptionPane.showMessageDialog(null, "<html>Good Notepad<br/>University of Chicago<br/>Copyright 2013<br/>Version 0.0.1</html>");
}
});
//set eventListeners
}
}
package lec09.glab.reflection;
/**
* Created with IntelliJ IDEA.
* User: ag
* Date: 11/18/13
* Time: 11:20 AM
* To change this template use File | Settings | File Templates.
*/
public class ReflectDriver {
public static void main(String[] args) {
// Rectangle recMe = new Rectangle(5,6,45,89);
// Reflector.printClass(recMe.getClass());
//
String strMe = "Adam";
Reflector.printClass(strMe.getClass());
// try {
// Reflector.printClass("java.lang.Double");
// } catch (ClassNotFoundException e) {
// e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
// }
}
}
package lec09.glab.reflection;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Scanner;
import java.util.Stack;
//originally found here: http://www.hackchina.com/en/r/18861/Reflector.java__html and grossly modified
//using Reflector and Horstmann as search params
public class Reflector {
public static void main(String[] args) {
// read class name from command line args or user input
// printClass(java.util.Date.class);
// return;
String strClass = "";
Scanner scan = new Scanner(System.in);
Class cls = null;
while (true) {
try {
System.out.println("Enter \"exit\" to quit, or a fully qualified class name (e.g. java.util.Date): ");
strClass = scan.next();
if (strClass.equalsIgnoreCase("exit")){
System.exit(0);
}
printClass(strClass);
} catch (ClassNotFoundException e) {
// e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
System.out.println("That's now a valid class name, try again.");
continue;
}
}
}
public static void printClass(Class cls) {
//create a stack and push the original class onto it
Stack<Class> clsStacks = new Stack<>();
clsStacks.push(cls);
//keep pushing its superclass until superclass is null (I've reached grand-daddy Object)
while (clsStacks.peek().getSuperclass() != null) {
clsStacks.push(clsStacks.peek().getSuperclass());
}
while (!clsStacks.empty()) {
cls = clsStacks.pop();
System.out.println("###############CLASS###############\n" +cls.toString() + "\n###############CLASS###############\n");
System.out.println("//INTERFACES");
printInterfaces(cls);
System.out.println("//FIELDS");
printFields(cls);
System.out.println();
System.out.println("//CONSTRUCTORS");
printConstructors(cls);
System.out.println();
System.out.println("//METHODS");
printMethods(cls);
System.out.println();
}
}
//overlaoded to take string
public static void printClass(String strClass) throws ClassNotFoundException {
Class cls;//the following line could throw an exception
cls = Class.forName(strClass);
printClass(cls);
}
public static void printConstructors(Class cl) {
Constructor[] constructors = cl.getDeclaredConstructors();
for (Constructor c : constructors) {
String name = c.getName();
System.out.print(" " + Modifier.toString(c.getModifiers()));
System.out.print(" " + name + "(");
// print parameter types
Class[] paramTypes = c.getParameterTypes();
for (int j = 0; j < paramTypes.length; j++) {
if (j > 0) System.out.print(", ");
System.out.print(paramTypes[j].getName());
}
System.out.println();//"); //no-arg constructor");
}
}
public static void printInterfaces(Class cl) {
System.out.print(" ");
Class[] interfaces = cl.getInterfaces();
for (int nC = 0; nC < interfaces.length; nC++) {
if (nC > 0) System.out.print(", ");
System.out.print(interfaces[nC].getName());
}
System.out.println();
System.out.println();
}
public static void printMethods(Class cl) {
Method[] methods = cl.getDeclaredMethods();
for (Method m : methods) {
Class retType = m.getReturnType();
String name = m.getName();
// print modifiers, return type and method name
System.out.print(" " + Modifier.toString(m.getModifiers()));
System.out.print(" " + retType.getName() + " " + name + "(");
// print parameter types
Class[] paramTypes = m.getParameterTypes();
for (int j = 0; j < paramTypes.length; j++) {
if (j > 0) System.out.print(", ");
System.out.print(paramTypes[j].getName());
}
System.out.println(");");
}
}
public static void printFields(Class cl) {
Field[] fields = cl.getDeclaredFields();
for (Field f : fields) {
String strMods = Modifier.toString(f.getModifiers());
Class type = f.getType();
String name = f.getName();
System.out.print(" " + Modifier.toString(f.getModifiers()));
System.out.println(" " + type.getName() + " " + name + ";");
}
}
}
\ No newline at end of file
......@@ -31,7 +31,7 @@ public class BinarySearchFrame extends JFrame
private Color colG = new Color( 1, 42, 42 );
private boolean bGuess = false;
private javax.swing.Timer timT;
private Timer timT;
private Comparable[] cA = new Integer[100];
private boolean bEmpty = true;
......@@ -81,7 +81,7 @@ public class BinarySearchFrame extends JFrame
{
contentPane = ( JPanel )getContentPane();
contentPane.setLayout( borderLayout1 );
setSize( new Dimension( 800, 250 ) );
setSize( new Dimension( 800, 600 ) );
setTitle( "Binary Search O(log n)" );
this.addWindowListener( new WindowAdapter()
{
......@@ -164,7 +164,7 @@ public class BinarySearchFrame extends JFrame
};
//the first parameter controls the delay
timT = new javax.swing.Timer( invertSliderValue( sldSpeed.getValue() ),
timT = new Timer( invertSliderValue( sldSpeed.getValue() ),
timerListener );
// createUnsortedArray();
......@@ -391,7 +391,7 @@ public class BinarySearchFrame extends JFrame
sldVal.setMaximum( panC.getHeight() );
sldVal.setMinimum( 0 );
//sldVal.setValue(panC.getHeight()/ 2);
sldVal.setValue(panC.getHeight()/ 2);
nR = 0;
nB = cA.length - 1;
nPR = nR;
......
package lec09.glab.searchsort;
import lec09.glab.structs.ListNode;
public class HashTable {
......
package lec09.glab.searchsort;
//inner class
class ListNode<T> {
private T typValue;
private ListNode<T> nodNext;
ListNode(T typInit, ListNode<T> nodInit) {
typValue = typInit;
nodNext = nodInit;
}
T getValue() {
return typValue;
}
ListNode<T> getNext() {
return nodNext;
}
void setValue(T typValue) {
this.typValue = typValue;
}
void setNext(ListNode<T> nodNext) {
this.nodNext = nodNext;
}
}
\ No newline at end of file
......@@ -31,7 +31,7 @@ public class QuickSortFrame extends JFrame
boolean bWait = true;
boolean bDone = false;
private javax.swing.Timer timT;
private Timer timT;
private Comparable[] cA = new Integer[100];
......@@ -77,7 +77,7 @@ public class QuickSortFrame extends JFrame
{
contentPane = ( JPanel )getContentPane();
contentPane.setLayout( borderLayout1 );
setSize( new Dimension( 800, 250 ) );
setSize( new Dimension( 800, 600 ) );
setTitle( "Quck Sort O(n log n)" );
this.addWindowListener( new WindowAdapter()
{
......@@ -159,7 +159,7 @@ public class QuickSortFrame extends JFrame
};
//the first parameter controls the delay
timT = new javax.swing.Timer( invertSliderValue( sldSpeed.getValue() ),
timT = new Timer( invertSliderValue( sldSpeed.getValue() ),
timerListener );
// createUnsortedArray();
......
......@@ -22,7 +22,7 @@ public class SelectionSortFrame extends JFrame
private int nY = 0;
boolean bWait = true;
private javax.swing.Timer timT;
private Timer timT;
private Comparable[] cA = new Integer[100];
private boolean bEmpty = true;
......@@ -68,7 +68,7 @@ public class SelectionSortFrame extends JFrame
{
contentPane = ( JPanel )getContentPane();
contentPane.setLayout( borderLayout1 );
setSize( new Dimension( 800, 250 ) );
setSize( new Dimension( 800, 600 ) );
setTitle( "Selection Sort O(n^2)" );
this.addWindowListener( new WindowAdapter()
{
......@@ -136,7 +136,7 @@ public class SelectionSortFrame extends JFrame
};
//the first parameter controls the delay
timT = new javax.swing.Timer( invertSliderValue( sldSpeed.getValue() ),
timT = new Timer( invertSliderValue( sldSpeed.getValue() ),
timerListener );
// createUnsortedArray();
......
......@@ -21,7 +21,7 @@ public class SeqSearchFrame extends JFrame
boolean bWait = true;
private Color colG = new Color( 1, 42, 42 );
private javax.swing.Timer timT;
private Timer timT;
private Comparable[] cA = new Integer[100];
private boolean bEmpty = true;
......@@ -67,7 +67,7 @@ public class SeqSearchFrame extends JFrame
{
contentPane = ( JPanel )getContentPane();
contentPane.setLayout( borderLayout1 );
setSize( new Dimension( 800, 250 ) );
setSize( new Dimension( 800, 600 ) );
setTitle( "Sequential Search O(n)" );
this.addWindowListener( new WindowAdapter()
{
......@@ -149,7 +149,7 @@ public class SeqSearchFrame extends JFrame
};
//the first parameter controls the delay
timT = new javax.swing.Timer( invertSliderValue( sldSpeed.getValue() ),
timT = new Timer( invertSliderValue( sldSpeed.getValue() ),
timerListener );
// createUnsortedArray();
......
package lec09.glab.simpledatastructs.hashmap;
import java.util.Map;
// this class is generic
public class SimpleHashMap<K,V> {
public class SimpleHashMap<K,V> {
private MapNode<K,V>[] nodHashes;
private HashMapNode<K,V>[] nodHashes;
private int nSize;
......@@ -14,14 +13,14 @@ public class SimpleHashMap<K,V> {
// ==CONSTRUCTOR
// ===============================================
public SimpleHashMap() {
nodHashes = new MapNode[1999];
nodHashes = new HashMapNode[1999];
nSize = 0;
}
//overlaoded
public SimpleHashMap(int nHashTableSize) {
nodHashes = new MapNode[nHashTableSize];
nodHashes = new HashMapNode[nHashTableSize];
nSize = 0;
}
......@@ -39,16 +38,16 @@ public class SimpleHashMap<K,V> {
// ==ADD
// ===============================================
//O(1) very fast
public void put(K typKey, V typValue) {
public void add(K typKey, V typValue) {
int nHash = typKey.hashCode();
nHash = Math.abs(nHash);
nHash = nHash % nodHashes.length;
MapNode<K,V> nodCurrent = nodHashes[nHash];
HashMapNode<K,V> nodCurrent = nodHashes[nHash];
if (nodCurrent == null) {
nodHashes[nHash] = new MapNode<K,V>(typKey,typValue, null);
nodHashes[nHash] = new HashMapNode<K,V>(typKey,typValue, null);
nSize++;
} else {
......@@ -63,7 +62,7 @@ public class SimpleHashMap<K,V> {
nodCurrent = nodCurrent.getNext();
}
if (!bFound){
nodHashes[nHash] = new MapNode<K,V>(typKey,typValue, nodHashes[nHash]);
nodHashes[nHash] = new HashMapNode<K,V>(typKey,typValue, nodHashes[nHash]);
nSize++;
}
......@@ -79,15 +78,15 @@ public class SimpleHashMap<K,V> {
public String contains(K typKey) {
String strR = "";
int nCount = 0; //just used to show how many times we had to iterate in the event of collission
int nCount = 0;
int nHash = typKey.hashCode();
nHash = Math.abs(nHash);
nHash = nHash % nodHashes.length;
MapNode<K,V> nodCurrent = nodHashes[nHash];
HashMapNode<K,V> nodCurrent = nodHashes[nHash];
while (nodCurrent != null) {
nCount++; //collission counter only
nCount++;
if (nodCurrent.getKey().equals(typKey)) {
strR += nodCurrent.getValue() + " found at index " + nHash + " : ";
break;
......@@ -120,7 +119,7 @@ public class SimpleHashMap<K,V> {
System.out.println(" : NULL");
}
else {
MapNode<K,V> nodCurrent = nodHashes[nC];
HashMapNode<K,V> nodCurrent = nodHashes[nC];
while (nodCurrent != null){
System.out.print( " : " + nodCurrent.getKey() + "-"+ nodCurrent.getValue());
nodCurrent = nodCurrent.getNext();
......@@ -138,13 +137,13 @@ public class SimpleHashMap<K,V> {
}
//inner class
class MapNode<K,V> {
class HashMapNode<K,V> {
private K typKey;
private V typValue;
private MapNode<K,V> nodNext;
private HashMapNode<K,V> nodNext;
MapNode(K typKey, V typValue, MapNode<K,V> nodNext) {
HashMapNode(K typKey, V typValue, HashMapNode<K,V> nodNext) {
this.typValue = typValue;
this.typKey = typKey;
this.nodNext = nodNext;
......@@ -163,7 +162,7 @@ public class SimpleHashMap<K,V> {
this.typKey = typKey;
}
MapNode<K,V> getNext() {
HashMapNode<K,V> getNext() {
return nodNext;
}
......@@ -171,7 +170,7 @@ public class SimpleHashMap<K,V> {
this.typValue = typValue;
}
void setNext(MapNode<K,V> nodNext) {
void setNext(HashMapNode<K,V> nodNext) {
this.nodNext = nodNext;
}
......
package lec09.glab.simpledatastructs.hashmap;
import java.util.HashMap;
import java.util.Map;
public class SimpleHashMapDriver {
/**
......@@ -11,46 +8,23 @@ public class SimpleHashMapDriver {
public static void main(String[] args) {
//try small numbers like 2, or 11
SimpleHashMap<Integer,String> strCities = new SimpleHashMap<Integer,String>(15);
Map<Integer, String> map= new HashMap<>();
System.out.println("hashcode() for 60001: " + new Integer(60001).hashCode());
System.out.println("hashcode() for 60001: " + new Integer(60001).hashCode());
//will not allow dups
strCities.put(60001, "Chicago");
strCities.put(60001, "Evanston");
strCities.put(20001, "New York");
strCities.put(90001, "Los Angeles");
strCities.put(99998, "Shanghai");
strCities.put(99999, "Moscow");
strCities.put(99999, "Moscow");
SimpleHashMap<Integer,String> strCities = new SimpleHashMap<Integer,String>(11);
//will not allow dups
map.put(60001, "Chicago");
map.put(60001, "Evanston");
map.put(20001, "New York");
map.put(90001, "Los Angeles");
map.put(99998, "Shanghai");
map.put(99999, "Moscow");
map.put(99999,"Moscow");
strCities.add(60001,"Chicago");
strCities.add(60001,"Evanston");
strCities.add(20001,"New York");
strCities.add(90001,"Los Angeles");
strCities.add(99998,"Shanghai");
strCities.add(99999,"Moscow");
strCities.add(99999,"Moscow");
strCities.printIterate();
System.out.println();
System.out.println(strCities.contains(99998));
System.out.println("#####################################");
//iter (using templates)
for (Integer integer : map.keySet()) {
System.out.println("Key: " + integer + " : Value: " + map.get(integer));
}
System.out.println(map.containsKey(99998));
......
......@@ -13,15 +13,16 @@ public class SimpleHashTable<T> {
// ==CONSTRUCTOR
// ===============================================
public SimpleHashTable() {
//the size should be approx twice the expected number of elements and prime
nodHashes = new Node[1999];
nSize = 0;
}
//overlaoded
//the load-factor of buckets should be around 75% full, which means there
// should be around 1.333 x the estimated number of elements for buckets
public SimpleHashTable(int nHashTableSize) {
nodHashes = new Node[nHashTableSize];
nodHashes = new Node[(int)(nHashTableSize * 1.333)];
nSize = 0;
}
......@@ -35,6 +36,7 @@ public class SimpleHashTable<T> {
}
// ===============================================
// ==ADD
// ===============================================
......@@ -51,7 +53,7 @@ public class SimpleHashTable<T> {
nodHashes[nHash] = new Node<T>(typ, null);
} else {
//put it to the beginning
//add it to the beginning
nodHashes[nHash] = new Node<T>(typ, nodHashes[nHash]);
......@@ -111,7 +113,8 @@ public class SimpleHashTable<T> {
else {
Node<T> nodCurrent = nodHashes[nC];
while (nodCurrent != null){
System.out.print( " : " + nodCurrent.getValue());
int nBucketIndex = Math.abs(nodCurrent.getValue().hashCode() % nodHashes.length);
System.out.print( " : " + nodCurrent.getValue() + " hash: " + nodCurrent.getValue().hashCode() + " % " + nodHashes.length + " = " + nBucketIndex );
nodCurrent = nodCurrent.getNext();
}
System.out.println();
......
package lec09.glab.simpledatastructs.hashtable;
import java.util.Date;
public class SimpleHashTableDriver {
/**
......@@ -9,25 +7,9 @@ public class SimpleHashTableDriver {
*/
public static void main(String[] args) {
//try small numbers like 2, or 11
SimpleHashTable<String> strCities = new SimpleHashTable<String>(11);
System.out.println("hashcode() for Chicago: " + "Chicago".hashCode());
System.out.println("hashcode() for Chicago: " + "Chicago".hashCode());
System.out.println("hashcode() for Date(12,15,2010): " + new Date(12,15,2010).hashCode());
System.out.println("hashcode() for Date(12,15,2010): " + new Date(12,15,2010).hashCode());
//hashcode() method of Date
// public int hashCode() {
// long ht = this.getTime();
// return (int) ht ^ (int) (ht >> 32);
// }
//try small numbers like 2, or 11, 50 and 51
SimpleHashTable<String> strCities = new SimpleHashTable<String>(5);
//will allow duplicates -- watch-out
strCities.add("Chicago");
strCities.add("New York");
......
......@@ -3,10 +3,13 @@ package lec09.glab.simpledatastructs.linkedlist;
import java.util.Iterator;
import java.util.List;
import java.util.ArrayList;
import java.util.SortedSet;
//this class is generic
public class SimpleLinkedList<T> {
private Node<T> nodFirst;
private Node<T> nodLast;
private int nSize;
......@@ -29,6 +32,8 @@ public class SimpleLinkedList<T> {
}
// ===============================================
......@@ -140,6 +145,7 @@ public class SimpleLinkedList<T> {
else {
Node<T> nodCurrent = nodFirst;
//we'll use zero-based when we iterate
for (int nC = 0; nC < nSize - 2; nC++) {
nodCurrent = nodCurrent.getNext();
}
......@@ -213,8 +219,6 @@ public class SimpleLinkedList<T> {
// ===============================================
public T getAtIndex(int nIndex) {
//Node<T> nodNew = new Node<T>(typ, null);
if (nIndex > nSize-1 || nIndex < 0)
throw new IndexOutOfBoundsException(
"index is beyond the range of this linked list.");
......@@ -328,7 +332,6 @@ public class SimpleLinkedList<T> {
}
//no setters, just getters
public int size() {
return nSize;
......@@ -417,7 +420,7 @@ public class SimpleLinkedList<T> {
@Override
public void remove() {
//we already have remove methods. not implemented.
throw new UnsupportedOperationException("Not supported");
}
}//end iterator
......
package lec09.glab.simpledatastructs.linkedlist;
import java.util.Iterator;
public class SimpleLinkedListDriver {
public static void main(String[] args) {
......@@ -32,19 +34,26 @@ public static void main(String[] args) {
//removeAtIndex working
System.out.println(strNames.removeAtIndex(3)); //expect Thomas
System.out.println("####################");
strNames.printIterate();
//getAtIndexWorking nSize working
System.out.println("####################");
System.out.println("########traverse the list using indices############");
System.out.println("########O(n^2)############");
for (int nC = 0; nC < strNames.size(); nC++) {
System.out.println(strNames.getAtIndex(nC));
}
System.out.println("#########use iterator to traverse list###########");
System.out.println("#########O(n)###########");
Iterator itrIterator = strNames.iterator();
while( itrIterator.hasNext()){
System.out.println(itrIterator.next());
}
}
}
}
......@@ -31,7 +31,7 @@ public class SimpleLinkedListTest {
strNames.addFirst("Adam");
assertEquals(strNames.getFirstValue(),"Adam");
assertEquals(3,strNames.size());
//the data-structure is not mutated
}
@Test
......@@ -39,7 +39,7 @@ public class SimpleLinkedListTest {
strNames.addLast("Thomas");
assertEquals(strNames.getLastValue(),"Thomas");
assertEquals(3,strNames.size());
//the data-structure is not mutated
}
@Test
......@@ -48,7 +48,7 @@ public class SimpleLinkedListTest {
String strAdam = strNames.removeFirst();
assertEquals(2, strNames.size());
assertEquals(strAdam,"Adam");
//the data-structure is not mutated
}
......@@ -59,7 +59,7 @@ public class SimpleLinkedListTest {
String strThomas = strNames.removeLast();
assertEquals(2,strNames.size());
assertEquals(strThomas,"Thomas");
//the data-structure is not mutated
}
......@@ -68,7 +68,7 @@ public class SimpleLinkedListTest {
String strBob = strNames.getAtIndex(0); //expect Bob
assertEquals(strBob, "Bob");
assertEquals(2,strNames.size());
//the data-structure is not mutated
}
@Test
......@@ -76,7 +76,7 @@ public class SimpleLinkedListTest {
String strBob = strNames.removeAtIndex(0); //expect Bob
assertEquals(strBob, "Bob");
assertEquals(1,strNames.size());
//the data-structure is not mutated
}
......@@ -87,7 +87,7 @@ public class SimpleLinkedListTest {
strNames.addAtIndex("Aaron",0);
assertEquals(strNames.getFirstValue(), "Aaron");
assertEquals(3,strNames.size());
//the data-structure is not mutated
}
}
......@@ -37,6 +37,7 @@ public class SimpleQueue<T> {
Node<T> nodNew = new Node<T>(typ, null);
//O(1)
//assume that both head and tail are null
if (nodHead == null) {
nodHead = nodNew;
nodTail = nodNew;
......
......@@ -4,6 +4,8 @@ package lec09.glab.simpledatastructs.queue;
public class SimpleQueueDriver {
public static void main(String[] args) {
System.out.println("First-In-First-Out"); //this is "fair"
SimpleQueue<String> strTeams = new SimpleQueue<String>();
......@@ -28,13 +30,16 @@ public static void main(String[] args) {
int nSize = strTeams.size();
for (int nC = 0; nC < nSize; nC++) {
System.out.println("dequeue " + strTeams.dequeue());
System.out.println("$$$$$$$$$$$$$result$$$$$$$$$$$$$$$");
strTeams.printIterate();
System.out.println("$$$$$$$$$$$$$result$$$$$$$$$$$$$$$");
}
System.out.println("The size of this queue is " + strTeams.size());
System.out.println("####################");
//strTeams.dequeue();
......
......@@ -76,9 +76,6 @@ public class SimpleStack<T> {
}
//used to print to screen
public void printIterate(){
Iterator<T> itr = this.iterator();
......@@ -104,10 +101,10 @@ public class SimpleStack<T> {
// return nodLast.getValue();
// }
public Node<T> getFirstNode() {
return nodTop;
}
// public Node<T> getFirstNode() {
//
// return nodTop;
// }
// public Node<T> getLastNode() {
//
......@@ -177,6 +174,7 @@ public class SimpleStack<T> {
@Override
public void remove() {
throw new UnsupportedOperationException("Not supported");
//we already have remove methods. not implemented.
}
......
......@@ -6,7 +6,8 @@ public class SimpleStackDriver {
public static void main(String[] args) {
SimpleStack<String> strTeams = new SimpleStack<String>();
System.out.println("First-In-Last-Out");
//addFirst and addLast are working
System.out.println("push Colts");
strTeams.push("Colts");
......@@ -21,9 +22,8 @@ public static void main(String[] args) {
//iterate over it
strTeams.printIterate();
System.out.println("The size of this stack is " + strTeams.size());
System.out.println("####################");
int nSize = strTeams.size();
for (int nC = 0; nC < nSize; nC++) {
......@@ -34,7 +34,7 @@ public static void main(String[] args) {
System.out.println("####################");
//strTeams.pop();
......
......@@ -9,33 +9,7 @@ public class SimpleTree {
nodHead = null;
}
public TreeNode getHead() {
return nodHead;
}
public Comparable decideLeftRight(Comparable comA, Comparable comB) {
if (((Comparable) comA).compareTo(comB) >= 0) {
return comA;
} else {
return comB;
}
}
public Comparable find(TreeNode nod) {
if (nod.getLeft() == null && nod.getRight() == null) {
return nod.getValue();
} else if (nod.getLeft() == null) {
return decideLeftRight(nod.getValue(), find(nod.getRight()));
} else if (nod.getRight() == null) {
return decideLeftRight(nod.getValue(), find(nod.getLeft()));
} else {
return decideLeftRight(
decideLeftRight(nod.getValue(), find(nod.getLeft())),
find(nod.getRight()));
}
}
//one-arg
//one-arg
public void insert(Comparable comVal) {
if (nodHead == null) {
......@@ -76,7 +50,13 @@ public class SimpleTree {
}
public void printInOrder(TreeNode nod) {
if (nod != null) {
//base case
if (nod == null){
//do nothing -- terminate
}
//recusive case
else {
printInOrder(nod.getLeft());
System.out.println(" Traversed " + nod.getValue());
printInOrder(nod.getRight());
......@@ -86,8 +66,8 @@ public class SimpleTree {
//inner class
//package access
class TreeNode {
private TreeNode nodL;
private Comparable comV;
private TreeNode nodL;
private TreeNode nodR;
public TreeNode(Comparable comInitValue, TreeNode nodLeft,
......
......@@ -9,19 +9,32 @@ public class SimpleTreeDriver {
public static void main(String[] args) {
SimpleTree comTeams = new SimpleTree();
//imbalanced
// comTeams.insert("Bears");
// comTeams.insert("Vikings");
// comTeams.insert("Browns");
// comTeams.insert("Jets");
// comTeams.insert("Cowboys");
// comTeams.insert("Patriots");
// comTeams.insert("Dolphins");
//more-balanced
//tier1
comTeams.insert("Dolphins");
//tier2
comTeams.insert("Cowboys");
comTeams.insert("Patriots");
//tier3
comTeams.insert("Bears");
comTeams.insert("Vikings");
comTeams.insert("Browns");
comTeams.insert("Jets");
SimpleTree comTeams = new SimpleTree();
comTeams.insert("Bears");
comTeams.insert("Vikings");
comTeams.insert("Browns");
comTeams.insert("Jets");
comTeams.insert("Cowboys");
comTeams.insert("Patriots");
comTeams.insert("Dolphins");
//try to comment this out
//comTeams.insert("Browns");
comTeams.printInOrder();
......
package lec10.glab.deadlock;
/**
* Created by ag on 11/30/2014.
*/
public class DeadLockDriver {
//notice that grandaddy Object has an implicit lock
public static Object sLock1 = new Object();
public static Object sLock2 = new Object();
public static void main(String args[]) {
ThreadDemo1 threadDemo1 = new ThreadDemo1();
ThreadDemo2 threadDemo2 = new ThreadDemo2();
threadDemo1.start();
threadDemo2.start();
}
private static class ThreadDemo1 extends Thread {
public void run() {
synchronized (sLock1) {
System.out.println("Thread 1: Holding lock 1...");
try { Thread.sleep(10); }
catch (InterruptedException e) {}
System.out.println("Thread 1: Waiting for lock 2...");
synchronized (sLock2) {
//this line is never reached because sLock2 is currently held
//and sLock1 is never released either because this does not terminate.
System.out.println("Thread 1: Holding lock 1 & 2...");
}
}
}
}
private static class ThreadDemo2 extends Thread {
public void run() {
synchronized (sLock2) {
System.out.println("Thread 2: Holding lock 2...");
try { Thread.sleep(10); }
catch (InterruptedException e) {}
System.out.println("Thread 2: Waiting for lock 1...");
synchronized (sLock1) {
//this line is never reached because sLock1 is currently held
//and sLock2 is never released either because this does not terminate.
System.out.println("Thread 2: Holding lock 1 & 2...");
}
}
}
}
}
\ No newline at end of file
package lec10.glab.future_callable;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.*;
/**
* Created with IntelliJ IDEA.
* User: ag
* Date: 11/30/13
* Time: 9:12 PM
* To change this template use File | Settings | File Templates.
*/
//https://blogs.oracle.com/CoreJavaTechTips/entry/get_netbeans_6
public class FutureDriver {
public static void main(String[] args) {
ExecutorService pool = Executors.newFixedThreadPool(3);
Callable<String> callableJavaClass = new WebsiteCallable("http://java-class.cs.uchicago.edu/");
Callable<String> callableAndroidClass = new WebsiteCallable("http://android.cs.uchicago.edu/");
//notice that the future object's generic maps directly to the Callable's generic.
Future<String> futureJava = pool.submit(callableJavaClass);
Future<String> futureAndroid = pool.submit(callableAndroidClass);
try {
//when this Callable task finishes, you can call the get() method on it's future
System.out.println(futureJava.get());
printSeperator(20);
System.out.println(futureAndroid.get());
} catch (InterruptedException e) {
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
} catch (ExecutionException e) {
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
}
System.exit(0);
}
private static void printSeperator(int nSep) {
for (int nC = 0; nC <nSep ; nC++) {
System.out.println("&&&&&&&&&&&&&&&&&&&&&&&&&&-SEPERATOR-&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&");
}
}
public static class WebsiteCallable
implements Callable<String> {
private String strUrl;
public WebsiteCallable(String strUrl) {
this.strUrl = strUrl;
}
//the Callable interface is genericized and it requires that the call method return the generic type
public String call() {
String strRet = "";
try {
URL urlObject = new URL(strUrl);
URLConnection con = urlObject.openConnection();
InputStream is =con.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(is));
String strLine = null;
while ((strLine = br.readLine()) != null) {
strRet += strLine + "\n";
}
} catch (IOException e) {
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
}
return strRet;
}
}
}
package lec10.glab.join;
/**
* Created with IntelliJ IDEA.
* User: ag
* Date: 11/30/13
* Time: 8:19 PM
* To change this template use File | Settings | File Templates.
*/
public class JoinDriver {
public static void main(String[] args) {
Thread thrOne = new Thread(new MyRunner1());
thrOne.start();
Thread thrTwo = new Thread(new MyRunner2());
thrTwo.start();
//try commenting-out this try block
try {
thrOne.join();
thrTwo.join();
} catch (InterruptedException e) {
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
}
System.out.println("Main thread done");
}
private static class MyRunner1 implements Runnable {
@Override
public void run() {
for (int nC = 0; nC < Short.MAX_VALUE * 10 ; nC++) {
nC++;
}
System.out.println("MyRunner1 done");
}
}
private static class MyRunner2 implements Runnable {
@Override
public void run() {
for (int nC = 0; nC < Short.MAX_VALUE * 20 ; nC++) {
nC++;
}
System.out.println("MyRunner2 done");
}
}
}
package lec10.glab.join;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLConnection;
/**
* Created with IntelliJ IDEA.
* User: ag
* Date: 11/30/13
* Time: 10:00 PM
* To change this template use File | Settings | File Templates.
*/
public class JoinWebDriver {
public static void main(String[] args) {
WebRunner webRunner = new WebRunner("http://java-class.cs.uchicago.edu/");
Thread thrWeb = new Thread(webRunner);
thrWeb.start();
//comment-out the following try-catch to see the difference in results.
//this joins thread thrWeb to the main thread.
try {
thrWeb.join();
} catch (InterruptedException e) {
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
}
System.out.println(webRunner.getReturnValue());
}
private static class WebRunner implements Runnable {
private String strUrl;
private String strReturnValue;
private WebRunner(String strUrl) {
this.strUrl = strUrl;
}
@Override
public void run() {
try {
String strRet = "";
URL urlObject = new URL(strUrl);
URLConnection con = urlObject.openConnection();
InputStream is = con.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(is));
String strLine = "";
while ((strLine = br.readLine()) != null) {
strRet += strLine + "\n";
}
strReturnValue = strRet;
} catch (IOException e) {
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
}
}
private String getReturnValue() {
return strReturnValue;
}
}
}
package lec10.glab.lambdas;
public class Circle implements Cloneable{
private int radius;
private int x;
private int y;
private String name;
private double area;
public Circle(int x, int y, int radius){
this.x = x;
this.y = y;
this.radius = radius;
this.area = 2 * Math.PI * radius;
}
public Circle(int x, int y, int radius, String name){
this.x = x;
this.y = y;
this.radius = radius;
this.name = name;
this.area = Math.PI * Math.pow(radius, 2);
}
public String getName() {
return this.name;
}
public int getRadius(){
return this.radius;
}
public int getX(){
return this.x;
}
public int getY(){
return this.y;
}
public double getArea(){
return this.area;
}
@Override
public String toString(){
return "I am " + this.name + ", area:" + this.area;
}
@Override
protected Circle clone() throws CloneNotSupportedException {
return (Circle)super.clone();
}
}
package lec10.glab.lambdas;
import java.util.Comparator;
public class Java7Comparator implements Comparator<Circle> {
/*
* This is our custom comparator for a Circle
* it compares the area of one circle to another
* */
@Override
public int compare(Circle o1, Circle o2) {
return Double.compare(o1.getArea(), o2.getArea());
}
}
package lec10.glab.lambdas;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;
public class Main {
public static void main(String... args){
ArrayList<Circle> theseCircles = new ArrayList<Circle>();
// Instantiate the Circles and put them in an array list
theseCircles.add(new Circle(200, 200, 23, "Jim"));
theseCircles.add(new Circle(25, 25, 15, "Bob"));
theseCircles.add(new Circle(430, 450, 29, "Batman"));
theseCircles.add(new Circle(180, 190, 30, "AntiJim"));
theseCircles.add(new Circle(20, 25, 20, "AntiBob"));
theseCircles.add(new Circle(425, 440, 40, "AntiBatman"));
// Java 7
System.out.println("Java 7 Results: ");
// Clone
ArrayList<Circle> j7Circles = new ArrayList<Circle>();
for (Circle c: theseCircles){
try {
j7Circles.add(c.clone());
} catch (CloneNotSupportedException cnse) {
System.out.println(cnse.getStackTrace());
}
}
// Sort (2 Possible Ways)
// Collections.sort(j7Circles, new Java7Comparator());
Collections.sort(j7Circles, new Comparator<Circle>() {
@Override
public int compare(Circle o1, Circle o2) {
return Double.compare(o1.getArea(), o2.getArea());
}
});
// Print Results
for (Circle c : j7Circles){
System.out.println(c.toString());
}
// Java 8
System.out.println("\n\nJava 8 Results: ");
// Clone
ArrayList<Circle> j8Circles = new ArrayList<Circle>();
// In theory (line will not compile!)
// theseCircles.forEach(c -> j8Circles.add(c.clone));
// Practical
theseCircles.forEach( c -> {
try {
j8Circles.add(c.clone());
} catch (CloneNotSupportedException cnse) {
System.out.println(cnse.getStackTrace());
}
});
Collections.sort(j8Circles, (Circle o1, Circle o2) -> Double.compare(o1.getArea(), o2.getArea()));
// Parameters Type Free Comparator
// Comparator<Circle> customComparator = (c1, c2) -> Double.compare(c1.getArea(), c2.getArea());
// Collections.sort(j8Circles, customComparator);
// Lambda Expressions that to the same thing
// j8Circles.forEach(c -> System.out.println(c));
j8Circles.forEach(System.out::println);
// Java 8 - Map Reduce Filter Collect
System.out.println("\n\nJava 8 Streams: ");
// We want to know the average area of our circles
double average = theseCircles
.stream()
.mapToDouble(Circle::getArea)
.average()
.getAsDouble();
System.out.println("\nAverage Area of all Circles: " + average);
// Lets now print the name of all circles whose are is above 2000
System.out.println("\nAll circles whose area is above 2000");
theseCircles
.stream()
.filter(c -> c.getArea() > 2000)
.forEach(System.out::println);
// Now we want to gather all the circles whose name begins with 'Anti'
System.out.println("\nAll whose name begins with 'Anti' ");
List<Circle> antiCircles = theseCircles
.stream()
.filter(c -> c.getName().startsWith("Anti"))
.collect(Collectors.toList());
antiCircles.forEach(System.out::println);
// Lets now print the circumference for each of the circles, along with their names
// Also sort by the circumference
System.out.println("\nCircle Circumferences");
theseCircles
.stream()
.sorted((c1, c2) -> Integer.compare(c1.getRadius(), c2.getRadius()))
.map(c -> c.getName() + ", circumference: " + c.getRadius() * 2 * Math.PI)
.forEach(System.out::println);
// We will emulate the functionality of collision detection in game using stream
// and in parallel
System.out.println("\n\nCollides");
Circle collisionCircle = new Circle(200, 400, 200, "Falcon");
theseCircles
.parallelStream()
.filter(c -> {
double radius2 = Math.pow((collisionCircle.getRadius() + c.getRadius()), 2);
double deltaX2 = Math.pow(Math.abs((collisionCircle.getX() - c.getX())), 2);
double deltaY2 = Math.pow(Math.abs((collisionCircle.getY() - c.getY())), 2);
return radius2 >= deltaX2 + deltaY2;
})
.forEach(c -> System.out.println("I " + c.getName() + " collided with " + collisionCircle.getName()));
}
}
package lec10.glab.lock;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class BankAccountExampleSynchronizedDriver {
/**
* @param args
*/
public static void main(String[] args) {
BankAccount bnk = new BankAccount();
final double AMOUNT = 100.0;
final int REPS = 100;
final int THREADS = 100;
for (int nC = 0; nC < THREADS; nC++) {
new Thread(new Depositer(bnk, AMOUNT, REPS)).start();
new Thread(new Withdrawer(bnk, AMOUNT, REPS)).start();
}
}
}
class Depositer implements Runnable{
private static final int DELAY = 1;
private BankAccount bnk;
private double dAmount;
private int nCount;
public Depositer(BankAccount bnk, double dAmount, int nCount) {
super();
this.bnk = bnk;
this.dAmount = dAmount;
this.nCount = nCount;
}
public void run(){
try {
for (int nC = 0; nC < nCount; nC++) {
bnk.deposit(dAmount);
Thread.sleep(DELAY);
}
} catch (InterruptedException exp) {
exp.printStackTrace();
}
}
}
class BankAccount {
Lock mLock;
private double dBalance;
public BankAccount() {
this.dBalance = 0;
mLock = new ReentrantLock();
}
//try commenting-out the mLock.lock() calls in the following two methods
// to see what happens
public void deposit(double dAmount){
mLock.lock();
try {
System.out.print("Depositing " + dAmount);
double dNewBal = getBalance() + dAmount;
System.out.println(", the new balance is "+ dNewBal);
setBalance(dNewBal);
} finally {
mLock.unlock();
}
}
public void withdraw(double dAmount){
mLock.lock();
try {
System.out.print("Withdrawing " + dAmount);
double dNewBal = getBalance() - dAmount;
System.out.println(", the new balance is "+ dNewBal);
setBalance(dNewBal);
} finally {
mLock.unlock();
}
}
public double getBalance() {
return this.dBalance;
}
public void setBalance(double dBalance) {
this.dBalance = dBalance;
}
}
class Withdrawer implements Runnable{
private static final int DELAY = 1;
private BankAccount bnk;
private double dAmount;
private int nCount;
public Withdrawer(BankAccount bnk, double dAmount, int nCount) {
super();
this.bnk = bnk;
this.dAmount = dAmount;
this.nCount = nCount;
}
public void run(){
try {
for (int nC = 0; nC < nCount; nC++) {
bnk.withdraw(dAmount);
Thread.sleep(DELAY);
}
} catch (InterruptedException exp) {
// TODO Auto-generated catch block
exp.printStackTrace();
}
}
}
/*
* This class is used in conjunction with the AtomicMain.java class to demonstrate
* the use of Atomic variables to maintain data integrity.
*/
package lec10.glab.more;
import java.util.logging.Level;
import java.util.logging.Logger;
public class AtomicAdder implements Runnable {
private final int addAmount = 100;
private AtomicBalance atomicBalance;
public AtomicAdder(AtomicBalance targetBalance){
this.atomicBalance = targetBalance;
}
@Override
public void run() {
try {
atomicBalance.transact(addAmount);
System.out.println("We added " + addAmount + " to the balance");
} catch (InterruptedException ex) {
Logger.getLogger(SynchAdder.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
/*
* This class is used in conjunction with the AtomicMain.java class to demonstrate
* how to use Atomic variables in order to ensure data integrity.
*
* Note that in the code below, I have // remarked out code that can be swapped with
* the code above it to show how the program would work WITHOUT atomic variables
* (hint: the ending result would be wrong).
*/
package lec10.glab.more;
import java.util.concurrent.atomic.AtomicInteger;
public class AtomicBalance {
AtomicInteger balance;
AtomicInteger tempBalance = new AtomicInteger();
// int balance;
// int tempBalance;
public AtomicBalance(int startingBalance){
this.balance = new AtomicInteger(startingBalance);
// this.balance = startingBalance;
}
public void transact(int amount) throws InterruptedException{
// >> This is where you would put in your actionable code <<
int readTemp = tempBalance.get();
while(!tempBalance.compareAndSet(readTemp, balance.intValue()))
readTemp = tempBalance.get();
// tempBalance = balance;
try {
Thread.sleep(20); // Instead of 'sleeping', a thread could be doing I/O functions that cause a delay, for example
} catch (InterruptedException e) {
}
// The 'AddAndGet' is unique to atomic variables. This method encapsulates the retrieval of and addition
// to a particular variable in a manner that is uninterruptible. Therefore, because we're using this method as
// opposed to tempBalance = tempBalance + amount, no other thread can be altering the tempBalance variable while
// we're working with it.
tempBalance.addAndGet(amount);
int readBalance = balance.get();
// The 'compareAndSet' command is based on compare and set feature found in modern microprocessors which provide for
// the uninterruptible check and replace function of specific data in memory. It follows the format:
// variableToChange.compareAndSet(expectedCurrentValue,valueWeWantToChangeTo);
// The program comfirms that the variableToChange value equals the expectedCurrentValue, and if it does, then
// it replaces the current value of the VariableToChange to the valueWeWantToChangeTo. If the variableToChange's value
// is NOT equal to expectedCurrentValue, then the current value is returned.
while(!this.balance.compareAndSet(readBalance, tempBalance.intValue()))
readBalance = balance.get();
/*
tempBalance += amount;
this.balance = tempBalance;
*/
}
public int currentAmount(){
return balance.intValue();
//return balance;
}
}
/*******************************************************************************
*
* Program: AtomicMain
*
* Purpose: Demonstrate the implementation of Atomic variables in Java. This
* code is essentially a revision of the program "SynchMain" which
* shows how to correctly structure a program so that attempts by
* concurrent threads to change a data value do not interfere with
* one another.
*
* In this program, we set up a "balance" object and then launch
* "adders" and "subtractors" to add and subtract value from this
* balance. As these objects run on separate threads, there's a risk
* of data contention - that is, two threads could read the value
* simultaneously and adjust it, leading to an incorrect outcome.
*
* When the program is running "correctly", the starting balance and
* the ending balance should be 100. If we decide to remove the
* use of atomic variables (see the AtomicBalance class for info on how
* to do this), we will end up with an incorrect ending balance.
*
******************************************************************************/
package lec10.glab.more;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;
public class AtomicMain {
public static void main (String args[]) {
AtomicBalance balance = new AtomicBalance(100);
ArrayList<Thread> threadList = new ArrayList<>();
System.out.println("Beginning amount = 100");
for(int i = 0; i < 10; i++){
AtomicAdder adder = new AtomicAdder(balance);
AtomicSubtractor subtractor = new AtomicSubtractor(balance);
Thread addThread = new Thread(adder);
Thread subThread = new Thread(subtractor);
threadList.add(addThread);
threadList.add(subThread);
addThread.start();
subThread.start();
}
// After we have launched all of our threads, we call the "join" method
// so that the program's flow will wait until all of the threads are completed.
// At this point, we can present the ending balance.
for (Thread thread : threadList) {
try {
thread.join();
} catch (InterruptedException ex) {
Logger.getLogger(SynchMain.class.getName()).log(Level.SEVERE, null, ex);
}
}
System.out.println("Ending amount = " + balance.currentAmount());
}
}
/*
* This class is used in conjunction with the AtomicMain.java class to demonstrate
* the use of Atomic variables to maintain data integrity.
*/
package lec10.glab.more;
import java.util.logging.Level;
import java.util.logging.Logger;
public class AtomicSubtractor implements Runnable {
private final int reductionAmount = -100;
private final AtomicBalance atomicBalance;
public AtomicSubtractor(AtomicBalance targetBalance){
this.atomicBalance = targetBalance;
}
@Override
public void run() {
try {
atomicBalance.transact(reductionAmount);
System.out.println("We reduced the balance by " + reductionAmount);
} catch (InterruptedException ex) {
Logger.getLogger(SynchSubtractor.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
\ No newline at end of file
/*
* This class should be reviewed in conjunction with the CallableMain.java class.
*/
package lec10.glab.more;
import java.util.Random;
import java.util.concurrent.Callable;
import java.util.concurrent.TimeUnit;
// This simple class sleeps for a pre-determined number of milliseconds
// and then return a random integer between 0 and 99.
// Because this class implements the Callable<Integer> interface, it must
// override the call() method and return an integer.
public class CallableGenerator implements Callable<Integer> {
private final Integer sleepNumber;
public CallableGenerator(Integer number){
this.sleepNumber = number;
}
@Override
public Integer call() {
// >> This is where you would put in your actionable code <<
// We first try to sleep for the assigned number of milliseconds.
// However, we look to check whether we are cancelled in the process
// You can imaginethat this class could be doing something
// instead of sleeping, like download a resource from the Internet,
// calculating a complex equation or converting one file to another.
try {
TimeUnit.MILLISECONDS.sleep(this.sleepNumber);
} catch (InterruptedException e) {
System.out.println("Darn, I've been cancelled!");
return 0;
}
// If we haven't been cancelled, we return our random number.
Random random = new Random();
return random.nextInt(100);
}
}
/************************************************************
*
* Program: CallableMain
*
* Purpose: To show how to use a ThreadPoolExecutor to
* launch, cancel and retrieve data from a series of
* threads using the Executor and Future class framework.
*
************************************************************/
package lec10.glab.more;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.*;
public class CallableMain {
public static void main (String args[]) throws InterruptedException {
System.out.println("\n*************************");
System.out.println("* System Starting *");
System.out.println("*************************\n");
// First, we create our Executor, which is used to execute and monitor callable objects.
ThreadPoolExecutor executor = (ThreadPoolExecutor)Executors.newFixedThreadPool(5);
// In this case, we created an Executor that will utilize a pool of 5 threads.
// For example, we could have also used a .newCachedThreadPool() which re-uses threads
// once they are done and is useful for short-term asynchronous tasks.
// Next, we create a list of Future objects of the type <Integer>, since that's what
// the CallableGenrator class returns. This will allow us to monitor and manage the
// thread's execution.
List<Future<Integer>> resultList = new ArrayList<>();
// For demonstration purposes, we create a random number generator
Random random = new Random();
// We then create 5 CallableGenerators (which implement the interface Callable<Integer>)
// and seed them with a random number between 5000 to 8000. This number tells the
// CallableGenerator to sleep that many milliseconds before returning a random integer
// between 0 and 99.
for(int i = 0; i < 5; i++){
Integer number = 5000 + random.nextInt(3000);
CallableGenerator generator = new CallableGenerator(number);
// When submitting the Callable Generator to the Executor, we receive back
// a Future of the type <Integer> that we can use to both monitor the status of,
// and get the value from, our generator. We can also use the Future to cancel
// a running task.
Future<Integer> result = executor.submit(generator);
// We then add this future to our list of futures. We will refer to this list
// later on in this program.
resultList.add(result);
}
System.out.println("All five threads have been created and started...");
System.out.println("We'll wait three seconds to cancel third task ...");
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
// We then ruthlessly cancel the third task in our list of futures,
// using the future object
Future<Integer> noFuture = resultList.get(3);
noFuture.cancel(true);
TimeUnit.SECONDS.sleep(1);
// With our thirst sated, we will wait until the rest of our tasks complete.
do {
System.out.println("Waiting for other tasks to complete ...");
TimeUnit.SECONDS.sleep(1);
// Because we used the ThreadPoolExecutor to construct our thread pool,
// we can monitor the number of tasks that have completed before
// we continue processing. This is not possible with the Executor or
// ExecutorService interfaces.
} while (executor.getCompletedTaskCount() < resultList.size());
System.out.println("All remaining tasks are now completed!");
// We then go through each future object on our list and retrieve the
// result from the associated CallableGenerator object.
for (int i = 0; i < resultList.size(); i++){
Future<Integer> finishedFuture = resultList.get(i);
// We check to see if this particular future is cancelled; if so,
// we do not want to use the .get()method, as this will generate
// a CancellecedException error.
try {
System.out.println("Task ID #: " + (i) + ") Cancelled? " + finishedFuture.isCancelled() + " Result = " + finishedFuture.get());
} catch (CancellationException ex) {
System.out.println("Task ID #: " + (i) + ") Cancelled? " + finishedFuture.isCancelled() + " Result = 0");
} catch (InterruptedException | ExecutionException ey){
ey.printStackTrace();
}
}
// Finally, we shut down the executor. If we fail to do this, it may continue
// running and cause us problems when we attempt to run this program again.
// Note that when this is called, the executor waits for the completion of tasks that are running or waiting
// for execution, and then finishes its execution.
executor.shutdown();
}
}
/*******************************************************************************
*
* Program: CollectionMain.java
*
* Purpose: To demonstrate the use of thread-safe collections.
*
* In this example, we are using the CopyOnWriteArrayList which
* which allows for concurrent reading and writing on a list.
* Specifically, we create a new CopyOnWriteArrayList in our
* main thread, and then pass this list to 25 instances of the
* CollectionTask class, each of which in turn roll 10 random numbers
* (values range from 0-9) and only add them to the list if they don't
* already appear there. We use the method ".addIfAbsent" which
* encapsulates the two commands .contains and .add to ensure that
* no two threads simultaneously add the same value to the list.
*
* Note that there are MANY other thread-safe collections in Java
* that perform a wide variety of functions.
*
*******************************************************************************/
package lec10.glab.more;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.ThreadPoolExecutor;
public class CollectionMain {
public static void main (String args[]){
CopyOnWriteArrayList list = new CopyOnWriteArrayList();
ArrayList<Future<?>> futureList = new ArrayList<>();
ThreadPoolExecutor executor = (ThreadPoolExecutor)Executors.newFixedThreadPool(25);
// We create 25 instances of the CollectionTask object, pass our list to it
// and start them running. Each will attempt to add random numbers to our list only
// if those numbers aren't already there.
for(int i = 0; i < 25; i++){
CollectionTask task = new CollectionTask(list);
futureList.add(executor.submit(task));
}
// We then wait for the process to complete
do {
} while (executor.getCompletedTaskCount() < futureList.size());
executor.shutdown();
// We then go through our list (which has been shared amongst 25 threads)
// and list the contents. We should not see any integer appear more than once.
// Note that when using an interator with a CopyOnWriteArray,
// you cannot remove an element.
Iterator itr = list.listIterator();
while(itr.hasNext()){
System.out.println(itr.next());
}
}
}
/*
* This class is used in conjunction with CollectionMain.java
*/
package lec10.glab.more;
import java.util.Random;
import java.util.concurrent.CopyOnWriteArrayList;
public class CollectionTask implements Runnable {
CopyOnWriteArrayList list;
// When this task is created, we receive the communal list
public CollectionTask(CopyOnWriteArrayList list){
this.list = list;
}
@Override
public void run() {
// >> This is where you would put in your actionable code <<
Random random = new Random();
for(int i = 0; i < 10; i++){
// We put the thread to sleep for a short period of time
// to allow for the opportunity of thread overalp on our list.
try {
Thread.sleep((long) Math.random() * 50 + 100);
} catch (InterruptedException e) {
e.printStackTrace();
}
// We add our randomly generated number to the list
// If we were using a regular array list, we'd have to use
// if(!ArrayList.contains(value)) { ArrayList.add(value); }
list.addIfAbsent(random.nextInt(10));
}
}
}
/*******************************************************************************
*
* Program: ExchangerMain
*
* Purpose: To provide a very simple example of how the Exchanger class
* works to allow threads to exchange object information at
* a central synchronization point.
*
* Put simply, this program creates an Exchanger object and passes
* it to two ExchangerParticpant objects, each of which sleeps
* for a random amount of time (between 5 and 15 seconds) before
* they attempt to exchange some data with the other.
*
* In this way, the Exchanger facilitates the communication of data
* across threads in a synchronized fashion when two threads need to
* exchange data but may be ready to do so at different times. Also,
* each ExchangerParticipant thread doesn't need to know anything about
* the other ExchangerParticipant thread, it only needs to know the
* Exchanger object.
*
* Source: Code adapted from example found at
* http://www.javacodex.com/Concurrency/Exchanger-Example
*
*******************************************************************************/
package lec10.glab.more;
import java.util.concurrent.Exchanger;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ExchangerMain {
public static void main(String args[]){
Exchanger<String> exchanger = new Exchanger<String>();
ExchangerParticipant a1 = new ExchangerParticipant(exchanger,"I like chocolate!");
ExchangerParticipant b1 = new ExchangerParticipant(exchanger,"I like peanut butter!");
ExecutorService executor = (ExecutorService)Executors.newFixedThreadPool(2);
executor.execute(a1);
executor.execute(b1);
executor.shutdown();
}
}
/*
* This class is used in conjunction with the ExchangeMain.java class.
* This class shows use a runnable class can use the Exchanger class to
* swap information with another thread without knowing anything about that thread.
*
*/
package lec10.glab.more;
import java.util.concurrent.Exchanger;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.logging.Logger;
public class ExchangerParticipant implements Runnable {
// When this object is initialized, it receives both an Exchanger object
// and a message.
Exchanger<String> exchanger;
String message;
public ExchangerParticipant(Exchanger<String> exchanger, String message){
this.exchanger = exchanger;
this.message = message;
}
@Override
public void run() {
// >> This is where you would put in your actionable code <<
// We disclose the message we were given initially
System.out.println("Thread ID# " + Thread.currentThread().getId() + " message: " + message);
// We then rest for some time between 5 and 15 seconds.
try {
long duration = 5 + (long)(Math.random() * 10);
System.out.println("Thread ID# " + Thread.currentThread().getId() + " will now sleep " + duration + " seconds before attempting an exchange ...");
TimeUnit.SECONDS.sleep(duration);
} catch (InterruptedException ex) {
Logger.getLogger(ExchangerParticipant.class.getName()).log(Level.SEVERE, null, ex);
}
// We then try to exchange a message with the other thread
// Note that the exchanger.exchange method is really the key function here, in that
// the thread will wait until the other thread is ready to complete the exchange.
// We could use a different version of the exchange method which allows for a timeout
// to be put in place, so that if the other thread is not ready to exchange data within X seconds
// (or milliseconds or minutes), we time out and can take other action.
try {
System.out.println("Thread ID# " + Thread.currentThread().getId() + " will now attempt to exchange data with other thread ...");
message = exchanger.exchange(message);
} catch (InterruptedException ex) {
Logger.getLogger(ExchangerParticipant.class.getName()).log(Level.SEVERE, null, ex);
}
// Finally, we print out the result of the exchange.
System.out.println("Thread ID# " + Thread.currentThread().getId() + " message: " + message);
}
}
/*****************************************************************************
*
* Program: ExectutorMain
*
* Purpose: This program shows how to initiate and use an Executor to
* run multiple threads.
*
* To see how to use an ExecutorService to initiate threads and
* process the results following each thread's completion, see
* the CallableMain.java class.
*
*****************************************************************************/
package lec10.glab.more;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
public class ExecutorMain {
public static void main (String args[]){
// To see the performance tuning opportunities with the newFixedThreadPool method,
// try adjusting the total number of threads avaiable in a pool - try 2 threads, 10, 50 and 100.
// Also compare the result by using a newCachedThreadPool, which will reuse threads when they are done.
// Note that an executor is limited in what it can do - for example, with an executor you cannot
// shut down an executor or determine whether a task is finished. You can't cancel a running task.
// For those things, you need an Executor Service.
Executor executor = Executors.newFixedThreadPool(10);
// ThreadPoolExecutor executor = (ThreadPoolExecutor)Executors.newCachedThreadPool();
for(int i = 0; i < 100; i++){
ExecutorTask targetTask = new ExecutorTask("Thread ID " + i);
executor.execute(targetTask);
}
}
}
/*
* Used in conjunction with the ExecutorMain.java class.
* This class implements the Runnable interface, and therefore can be
* executed and monitored by an Executor.
*/
package lec10.glab.more;
import java.util.Date;
public class ExecutorTask implements Runnable {
final private String name;
public ExecutorTask(String targetName){
this.name = targetName;
}
@Override
public void run() {
// >> This is where you would put in your actionable code <<
System.out.println(this.name + " starting at " + new Date());
try{
Thread.sleep((long)(Math.random() * 3000));
} catch (InterruptedException e) {
}
System.out.println(this.name + " ending at " + new Date());
}
}
/*******************************************************************************
*
* Program: ForkJoinMain.java
*
* Purpose: To demonstrate the fork/join framework. In this program,
* we create an array of 100,000 random integers ranging from
* 0 to 99,999 and we seek to find the lowest value.
*
* To do this, we create a task that does this by breaking up
* the data in half, recursively, until less than 5 elements
* appear in the data list, and then finds the lowest
* integer value iteratively. It uses the fork/join framework
* to allocate portions of this task to background threads.
* Be sure to check out the code in "ForkJoinTask.java" for
* more information on how this is done.
*
* Source: This program is based on code found at:
* http://www.javacodegeeks.com/2013/02/java-7-forkjoin-framework-example.html
*
*******************************************************************************/
package lec10.glab.more;
import java.util.Random;
import java.util.concurrent.ForkJoinPool;
public class ForkJoinMain {
public static void main(String args[]){
// We first create a data array of 100,000 random integers
// ranging from 0 to 99,999
final int data[] = new int[100000];
final Random random = new Random();
for(int i = 0; i < data.length; i++){
data[i] = random.nextInt(100000);
}
// We then create a Fork/Join pool with 4 threads in it
// and pass along the task for it to run.
final ForkJoinPool pool = new ForkJoinPool(4);
final ForkJoinTask task = new ForkJoinTask(data);
System.out.println("The lowest number found is " + pool.invoke(task));
}
}
/*
* This class should be viewed in conjunction with ForkJoinMain.java
*
* It is based on code found at:
* http://www.javacodegeeks.com/2013/02/java-7-forkjoin-framework-example.html
*/
package lec10.glab.more;
import java.util.concurrent.RecursiveTask;
// Note that as a designated recursiveTask, this class must implement the
// "compute()" method below and return an integer. If we had, instead,
// worked on a project that did not need us to return a value, we could extend
// the RecursiveAction class.
// In this case, we are returning an integer.
public class ForkJoinTask extends RecursiveTask<Integer> {
// This value tells us that if we are examining a list that has less
// than 5 elements in it, we will search for the lowest value by simply
// looping through the list and identifying the lowest value.
private static final int THRESHOLD = 5;
private final int[] data;
private final int start;
private final int end;
// We actually have two constructors, one of which takes just a list of
// data while the other takes the data, plus a start and end point.
public ForkJoinTask(int[] data, int start, int end){
this.data = data;
this.start = start;
this.end = end;
}
public ForkJoinTask(int[] data){
this(data,0,data.length);
}
// This method is required by the fact that we're extending the RecursiveTask<Integer>
// class. This method checks to see if our current list is less than 'Threshold'
// elements, and if so, passes it to the computeDirectly() method; otherwise, it splits
// the task into two subtasks which each begin this process again.
@Override
protected Integer compute() {
// >> This is where you would put in your actionable code <<
// >> if you were performing a different task. <<
final int length = end - start;
if (length < THRESHOLD) {
return computeDirectly();
}
final int split = length / 2;
final ForkJoinTask left = new ForkJoinTask(data, start, start + split);
left.fork(); // We send it off to be executed on a separate thread
final ForkJoinTask right = new ForkJoinTask(data, start + split, end);
// By calling the left.join() method, we retrieve the value from the
// left fork after it is completed.
return Math.min(right.compute(), left.join());
}
// This simple method finds the lowest value in a list by looping through
// each element. It is only used on lists that have fewer than 'THRESHOLD'
// elements in it (default value is 5).
private Integer computeDirectly() {
System.out.print(Thread.currentThread() + " computing elements " + start + " to " + end + " : ");
for (int nC = start; nC <end ; nC++) {
System.out.print(data[nC] + " ");
}
System.out.println();
// System.out.println(" computing elements " + start + " to " + end);
int min = Integer.MAX_VALUE;
for (int i = start; i < end; i++) {
if (data[i] < min) {
min = data[i];
}
}
return min;
}
}
/*
* This code is to be used in conjunction with the LatchMain.java class.
*/
package lec10.glab.more;
import java.util.concurrent.CountDownLatch;
public class LatchGame implements Runnable {
private final CountDownLatch controller; // This is our latch
// When our game is constructed, we tell it how many players will be joining
public LatchGame(int number){
System.out.println("A new game has been initialized ...");
controller = new CountDownLatch(number);
}
public void arrive(String name){
System.out.printf("%s has arrived ... \n",name);
controller.countDown(); // This is critical as it tells the latch that we're getting closer to goal
System.out.printf("still waiting for %d participants.\n",controller.getCount());
}
@Override
public void run() {
// >> This is where you would put in your actionable code <<
System.out.println("Launching game with " + controller.getCount() + " players ... \n");
try {
controller.await(); // We pause this thread until our latch has reached zero
System.out.println("\nAll the players have arrived!");
System.out.println("Let the games begin!");
} catch (InterruptedException e){
e.printStackTrace();
}
}
}
/*******************************************************************************
*
* Program: LatchMain.Java
*
* Purpose: This program is designed to show the benefit of using a
* CountDownLatch as a thread synchronized to better manage multiple
* threads.
*
* In this program, we pretend that we're setting up a multi-player
* game. However, gameplay cannot commence until all 10 "warriors"
* join the game. By using the CountDownLatch, we can more efficiently
* manage thread execution to wait until all 10 players join and
* the game can begin.
*
* If a multiplayer game doesn't seem appropriate to you, you can
* imagine this same mechanism being used by a multi-threaded simulator
* that requires for a bunch of threads to be initialized before
* starting a complicated simulation. Using the CountDownLatch
* synchronizer, it's easy to set up such a program.
*
* Source: This code was adapted from an example using videoconferencing
* as a metaphor in Gonzalez, Java 7 Concurrency Cookbook, (pp. 92-97).
*
*******************************************************************************/
package lec10.glab.more;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class LatchMain {
public static void main(String args[]){
System.out.println("\n******************");
System.out.println("* DEMO BEGINS *");
System.out.println("******************\n");
ExecutorService executor = (ExecutorService)Executors.newFixedThreadPool(11);
LatchGame game = new LatchGame(10);
executor.execute(game);
for (int i = 0; i < 10; i++) {
LatchPlayer player = new LatchPlayer(game,"Warrior #" + i);
executor.execute(player);
}
executor.shutdown();
}
}
/*
* This code is to be used in conjunction with the LatchMain.java class.
*/
package lec10.glab.more;
import java.util.concurrent.TimeUnit;
public class LatchPlayer implements Runnable {
private final LatchGame latchGame;
private final String playerName;
// When we create our player, we tell it which game to join and give a name
public LatchPlayer(LatchGame latchGame, String name){
this.latchGame = latchGame;
this.playerName = name;
}
@Override
public void run() {
// Before joining the game, the player sleeps between 5 and 15 seconds
try {
TimeUnit.SECONDS.sleep(5 + (long)(Math.random()*10));
} catch (InterruptedException e){
e.printStackTrace();
}
// The player then joins the game
latchGame.arrive(playerName);
}
}
/*
* This class is used in conjunction with the LockMain.java class.
*/
package lec10.glab.more;
// The LockJob is constructed with a LockTarget which is a task that whose
// internal lock must be acquired by this LockJob before this LockJob can
// complete its job.
public class LockJob implements Runnable {
private final LockTarget lockTarget;
public LockJob(LockTarget lockTarget){
this.lockTarget = lockTarget;
}
@Override
public void run() {
System.out.println("[LockJob ] Thread ID # " + Thread.currentThread().getId() + ": going to start new job");
// Tries to do the job (which requires acquiring the target's lock). If the lock is
// unavailable, the program blocks and waits.
lockTarget.doJob(new Object());
// Once the lock is freed, the job is completed and the program can continue.
System.out.println("[LockJob ] Thread I D# " + Thread.currentThread().getId() + ": job is finished");
}
}
/*****************************************************************
*
* Program: LockMain.java
*
* Purpose: To demonstrate the ease and utility of using the
* java.concurrent.lock mechanism to ensure data
* integrity
*
*****************************************************************/
package lec10.glab.more;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class LockMain {
public static void main (String args[]){
// We first create a LockTarget object, which has its own lock
// that must be acquired by a thread before it can do its job.
LockTarget lockTarget = new LockTarget();
ExecutorService executor = (ExecutorService)Executors.newFixedThreadPool(10);
// We then create 10 LockJobs that will attempt to access the LockTarget
// (and its single lock) to complete their jobs.
for(int i = 0; i < 10; i++){
executor.execute(new LockJob(lockTarget));
}
executor.shutdown();
}
}
/*
* This class is used in conjunction with the LockMain.java class.
*/
package lec10.glab.more;
import java.util.Date;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class LockTarget {
// The target has its own lock
private final Lock targetLock = new ReentrantLock();
public void doJob(Object target){
// Before continuing, it acquires the lock
// If it is unable to do so, it waits.
targetLock.lock();
try {
// >> This is where you would put in your actionable code <<
Long sleepInterval = ((long)Math.random()) * 5000 + 1000;
// This could be accessing an output resource
System.out.println("[LockTarget] Thread ID # " + Thread.currentThread().getId() + ": started job at " + new Date());
Thread.sleep(sleepInterval);
System.out.println("[LockTarget] Thread ID # " + Thread.currentThread().getId() + ": finished job at " + new Date());
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
targetLock.unlock();
// It is a requirement to include the targetLock.unlock() call as part of "finally", so that
// in the event that the thread crashes (or is interrupted), the lock is released no matter what.
}
}
}
\ No newline at end of file
/*
* This class should be used in conjunction with the SemaphoreMain.java class.
*/
package lec10.glab.more;
public class SemaphoreJob implements Runnable {
private SemaphoreQueue semaphorequeue;
public SemaphoreJob(SemaphoreQueue semaphorequeue){
this.semaphorequeue = semaphorequeue;
}
public void run() {
System.out.println("Thread ID# " + Thread.currentThread().getId() + " starting job");
// At this point, the job attempts to use the queue but it may have to wait, if more than
// the allowed number of threads is seeking to use this resource.
semaphorequeue.doJob(new Object());
System.out.println("Thread ID# " + Thread.currentThread().getId() + " job has finished.");
}
}
/*******************************************************************************
*
* Program: SemaphoreMain.java
*
* Purpose: To demonstrate the use of semaphores to allow for shared
* but managed access to a shared resource. In this program, we
* create a "semaphorequeue" (which we could imagine to be any
* shared resource, like an output device, etc.) and we create
* 10 jobs that seek to use this queue. As each job starts,
* we see that only the first 2 jobs finish immediately, and then
* the other jobs in turn are able to start and finish. This is
* because we initialized our semaphore (in class SemaphoreQueue)
* with a value of 2.
*
* We could have also used the tryAcquire method to gain the semaphore,
* much as with a lock, which would give us the ability to do other
* business while we await for the semaphore to become free again.
*
* Source: This code was adapted from Gonzalez, Java 7 Concurrency Cookbook, pp. 84-87.
*
*******************************************************************************/
package lec10.glab.more;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class SemaphoreMain {
public static void main(String args[]){
SemaphoreQueue semaphorequeue = new SemaphoreQueue();
ExecutorService executor = (ExecutorService)Executors.newFixedThreadPool(10);
for(int i = 0; i < 10; i++){
SemaphoreJob job = new SemaphoreJob(semaphorequeue);
executor.execute(job);
}
executor.shutdown();
}
}
/*
* This class should be used in conjunction with the SemaphoreMain.java class.
*/
package lec10.glab.more;
import java.util.concurrent.Semaphore;
public class SemaphoreQueue {
private final Semaphore semaphore;
public SemaphoreQueue() {
// We initialize our semaphore with a value of 2. We could initialize it
// with a value greater of 1 -- which would make the semaphore akin to a lock,
// (or N), which would allow 'N' threads to access the queue simultaneously.
semaphore = new Semaphore(2);
}
public void doJob (Object targetObject){
try {
semaphore.acquire();
// >> This is where you would put in your actionable code <<
System.out.println("Job commenced");
Thread.sleep((long)Math.random() * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
semaphore.release();
}
}
}
/****************************************************************
*
* Program: SimpleThread (main method at SimpleThreadMain.java)
*
* Purpose: To demonstrate how to launch multiple-threads
* using Java's basic threading model. This
* particular program launches a thousand threads
* which each take a random number between 500
* million and a billion and calculate the prime
* factorization of that number.
*
* Code Source: The code for calculating the prime factorization is based
* on code found at:
* http://www.vogella.com/tutorials/JavaAlgorithmsPrimeFactorization/article.html
*
****************************************************************/
package lec10.glab.more;
import java.util.ArrayList;
import java.util.Random;
// In order to run a class's methods using a thread, that class has to either
// implement the 'Runnable' interface or it has to extend the Thread class.
// If you take the route of extending the Thread class, your object can't extend any
// other classes (due to Java's single inheritance requirement). However, if
// you decide to implement the Runnable interface, you have to create an object
// of the Thread class and pass the Runnable object as a parameter (see 'SimpleThreadMain.java').
public class SimplePrimeFactor implements Runnable {
// These variable are used for the prime factorization function
int number;
ArrayList<Integer> factors;
// When creating our object, we seed it with a very large random number
public SimplePrimeFactor(){
Random rand = new Random();
this.number = (500000000 + rand.nextInt(500000000));
}
// This is the function that will be run on its own, unique, thread
@Override
public void run() {
// >> This is where you would put in your actionable code <<
factors = new ArrayList<Integer>();
int n = number;
for (int i = 2; i <= n / i; i++) {
while (n % i == 0) {
factors.add(i);
n /= i;
}
}
if (n > 1) {
factors.add(n);
}
// Display the results when finished. Note that we have to use the 'synchronized' keyword to ensure that
// we don't have threads printing out to the console at the same time, causing overlap
// Note that this object will print out it's thread name once it is done with factoring its number.
// Besides the name, you can get a thread's ID, priority (between 1 and 10) and status (new, runnable, waiting,
// timewaiting, or terminated).
synchronized (System.out){
System.out.printf(Thread.currentThread().getName() + ": The prime factors for " + number + " are: ");
for (int i = 0; i < factors.size(); i++){
System.out.printf(factors.get(i) + ", ");
}
System.out.printf("\n");
}
}
}
/****************************************************************
*
* Program: SimpleThread
*
* Purpose: To demonstrate how to launch multiple-threads
* using Java's basic threading model. This
* particular program launches a thousand threads
* which each take a random number between 500
* million and a billion and calculate the prime
* factorization of that number.
*
* Code Source: The code for calculating the prime factorization is based
* on code found at:
* http://www.vogella.com/tutorials/JavaAlgorithmsPrimeFactorization/article.html
*
****************************************************************/
package lec10.glab.more;
public class SimpleThreadMain {
public static void main(String args[]){
for(int i = 0; i < 1000; i++){
new Thread(new SimplePrimeFactor()).start();
}
}
}
/*
* This code is used in conjunction with the classes SynchMain.java and
* SynchBalance.java. This particular class, when called, adds 100
* to the balance.
*
* Note that because this code implements the Runnable interface, it can be
* placed within a thread.
*/
package lec10.glab.more;
import java.util.logging.Level;
import java.util.logging.Logger;
public class SynchAdder implements Runnable {
private final int addAmount = 100;
private SynchBalance synchBalance;
public SynchAdder(SynchBalance targetBalance){
this.synchBalance = targetBalance;
}
@Override
public void run() {
try {
synchBalance.transact(addAmount);
System.out.println("We added " + addAmount + " to the balance");
} catch (InterruptedException ex) {
Logger.getLogger(SynchAdder.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
/*
* This class is used in conjunction with the SynchMain.java class.
*
* To demonstrate the utility of the synchronization keyword, we have created
* a (somewhat contrived) method that shows the dangers when threads are able to access data
* concurrently without any preventative steps taken to ensure data integrity.
*
* In this case, because the thread sleeps for a small amount of time before completing the
* transaction, it's possible for multiple threads to start transactions concurrently before
* previous transactions are completed. This can lead to corrupt data.
*
* To minimize this, you can place the 'synchronized' keyword between 'public' and 'void'
* in the transact method, which will prevent a later thread from accessing this method
* until a prior thread completes the method, thereby ensuring data integrity.
*
*/
package lec10.glab.more;
public class SynchBalance {
int balance = 0;
int tempBalance = 0;
public SynchBalance(int startingBalance){
this.balance = startingBalance;
}
// With the term 'synchronized' remarked out, this program will not
// generate the correct sequence of transactions, leading to an incorrect
// balance at the end.
public /* synchronized */ void transact(int amount) throws InterruptedException{
// >> This is where you would put in your actionable code <<
tempBalance = balance;
try {
Thread.sleep(20); // Instead of 'sleeping', a thread could be doing I/O functions that cause a delay
} catch (InterruptedException e) {
}
tempBalance += amount;
this.balance = tempBalance;
}
public int currentAmount(){
return balance;
}
}
/*
* This example shows the utility of using the 'synchronized' keyword to
* protect the integrity of a variable that is accessed by multiple threads.
*
* This program does one simple task - it sets up an initial balance of 100 and then
* adds and subtracts 100 an equal number of times until completion. Consequently,
* the ending balance should be 100.
*
* To test this code, run it first in its present form, and see that the beginning and
* ending balances are different, although the amounts added and subtracted are equal.
* Next, activate the "synchronized" keyword between 'public' and 'class' in the SynchBalance
* class and re-run the program. The beginning balance and ending balance will equal.
*
* This code is adapted from examples found in the tutorial "Java 101: Understanding
* Threads, Part 2: Java Synchronization" by Jeff Friesen, located at:
* http://www.javaworld.com/article/2074318/java-concurrency/java-101--understanding-java-threads--part-2--thread-synchronization.html
* as well as the book "Java 7 Concurrency Cookbook" by Javier Fernandez Gonzalez (pg. 46).
*/
package lec10.glab.more;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;
public class SynchMain {
public static void main (String args[]) {
SynchBalance balance = new SynchBalance(100);
ArrayList<Thread> threadList = new ArrayList<>();
System.out.println("Beginning amount = 100");
for(int i = 0; i < 10; i++){
SynchAdder adder = new SynchAdder(balance);
SynchSubtractor subtractor = new SynchSubtractor(balance);
Thread addThread = new Thread(adder);
Thread subThread = new Thread(subtractor);
threadList.add(addThread);
threadList.add(subThread);
addThread.start();
subThread.start();
}
// After we have launched all of our threads, we call the "join" method
// so that the program's flow will wait until all of the threads are completed.
// At this point, we can present the ending balance.
for (Thread thread : threadList) {
try {
thread.join();
} catch (InterruptedException ex) {
Logger.getLogger(SynchMain.class.getName()).log(Level.SEVERE, null, ex);
}
}
System.out.println("Ending amount = " + balance.currentAmount());
}
}
/*
* This code is used in conjunction with the classes SynchMain.java and
* SynchBalance.java. This particular class, when called, subtracts 100
* to the balance.
*
* Note that because this code implements the Runnable interface, it can be
* placed within a thread.
*/
package lec10.glab.more;
import java.util.logging.Level;
import java.util.logging.Logger;
public class SynchSubtractor implements Runnable {
private final int reductionAmount = -100;
private final SynchBalance synchBalance;
public SynchSubtractor(SynchBalance targetBalance){
this.synchBalance = targetBalance;
}
@Override
public void run() {
try {
synchBalance.transact(reductionAmount);
System.out.println("We reduced the balance by " + reductionAmount);
} catch (InterruptedException ex) {
Logger.getLogger(SynchSubtractor.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
/*
* Use this class in conjunction with TryLockMain.java
*/
package lec10.glab.more;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
public class TryLockJob implements Runnable {
private final Lock passLock;
// We receive the lock as part of the object construction process
public TryLockJob(Lock passLock){
this.passLock = passLock;
}
@Override
public void run() {
do {
try {
if(passLock.tryLock(1, TimeUnit.SECONDS)) {
try {
System.out.println("Thread ID #" + Thread.currentThread().getId() + " successfully acquired thread lock.");
// ***** DO PROTECTED WORK HERE ****** //
Thread.sleep(5000);
} finally {
passLock.unlock();
System.out.println("Thread ID #" + Thread.currentThread().getId() + " is finished and unlocked thread lock.");
}
break;
} else {
System.out.println("Thread ID #" + Thread.currentThread().getId() + " unable to acquire thread lock and will try again.");
// ****** DO OTHER WORK WHILE WAITING FOR LOCK RELEASE ******* //
}
} catch (InterruptedException e){
e.printStackTrace();
}
} while (true);
}
}
/*******************************************************************************
*
* Program: TryLockMain.java
*
* Purpose: To show how to use the TryLock method to avoid blocking
* when attempting to access a shared resource across multiple
* threads. In this example, we pass a lock to three instances
* of a runnable task, each of which attempt to complete a 5
* second task by unlocking the lock. If they are unable to
* unlock the lock, they indicate so and try again in 1 second.
* *
* Source: This example was adapted from code found at:
* http://robaustin.wikidot.com/reentrantlock.
*
*******************************************************************************/
package lec10.glab.more;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class TryLockMain {
// We create a new lock that we're going to pass to each job.
final Lock passLock = new ReentrantLock();
public static void main(String args[]){
new TryLockMain().go();
}
private void go() {
System.out.println("\n*********************");
System.out.println("* STARTING DEMO *");
System.out.println("*********************\n");
ExecutorService executor = (ExecutorService)Executors.newFixedThreadPool(3);
for(int i = 0; i < 3; i++){
TryLockJob job = new TryLockJob(passLock);
executor.execute(job);
}
executor.shutdown();
}
}
***********************************************
* JALABCONCURRENCY MSTRP BRANCH *
* INDEX OF PROGRAMS *
***********************************************
//All the classes in this package were created by Micheal Strupp for Advanced Java. They are used here with his permission.
“AtomicMain.java” – This program shows two independent threads adding and subtracting values to a common "balance" variable.
It demonstrates the benefit of using atomic integers to ensure data integrity when two or more threads may alter a piece of common data.
This is a revision of SynchMain program (below).
“CallableMain.java” – This program starts five independent threads which each return a random integer. However, before the threads finish,
the main program cancels one of the threads and once the remaining threads finish, retrieves the numbers they generated. In effect, this
program shows how to run, cancel and retrieve data from threads using the Executor class, Future objects and the Callable interface.
“CollectionMain.java” – This program launches 25 independent threads, each of which attempt to add a random integer between 0 and 9 to a common
list. By using the CopyOnWriteArrayList and its "AddIfAbsent" method, this program demonstrates how Java's concurrent collection classes make it
easy to manage list access across multiple threads.
“ExchangerMain.java” – This is a very simple demonstration of swapping objects across threads using the Exchanger synchronization utility.
In this program, two threads are created. When they start, they sleep for a random amount of seconds (between 5 and 15), they then engage the Exchanger
utility to swap out a text message with each other.
“ExecutorMain.java” – This is a simple program showing how to use a simple Executor to execute a runnable task.
“ForkJoinMain.java” – This program creates a data array of 100,000 random integers with a value between 0 and 99,999 and seeks to return the lowest
value using recursive techniques. It does this by using the new fork/join thread framework, which allows a program to easily split and re-join
threads in order to break down a larger task into smaller tasks, and then re-assemble them easily to arrive at a final answer.
“LatchMain.java” – This is another demonstration of a Java thread synchronizer utility. In this program, a new "game" is started on a thread and
the game "waits" until 10 players join the game before beginning the competition. Each player is, itself, a thread. This program demonstrates
how to use Java's CountDownLatch mechanism to synchronize the initiation and joining of threads.
“LockMain.java” – This is a simple program showing how to use a Java Lock object to prevent multiple threads from accessing the same code at the
same time. See the program below called "TryLockMain.java" for an extension of this program.
“SemaphoreMain.java” – This program demonstrates the use of semaphores to allow concurrent access to a shared resource. In this program, we create
a "queue" that 10 different threads are attempting to access. The semaphore object only allows 2 threads to access the queue at the same time
(we could imagine that 2 is the limit that this queue permits). In this way, a semaphore is like a lock but with greater flexibility.
“SimpleThreadMain.java” – In this program, we launch 1,000 threads consisting of objects that calculate the prime factorization of a number
between 500 million and a billion. In effect, this program showcases the "old school" way in which Java launches multiple background threads
to complete a task. You should contrast this with the "CallableMain.java" program and the "ExecutorMain.java" program to see how to accomplish
similar tasks, with much more control, using the Executor framework.
“SynchMain.java” – In this program, we create a "balance" object, along with "adder" and "subtractor" objects that seek to add and subtract
value from the balance using concurrent threads. While this could potentially lead to problems, the use of the "synchronized" keyword provides
one mechanism for ensuring that thread overlapping doesn't occur. You should contrast this method with the "LocksMain.java", the "TryLocksMain.java"
and the "AtomicMain.java" demonstration programs, which represent alternativ ways to solve the concurrent-access-to-data problem.
“TryLockMain.java” – In this program, we launch three threads that simultaneously attempt to complete a job but must first acquire a lock to do
so. By using the tryLock() method, threads can see whether the lock is available and, if not, do other work while waiting for the lock to be released.
This program can be contrasted with the "SynchMain.java" program, in which the use of the "synchronized" keyword leads to thread blocking while
a particular piece of code is being used by another thread.
\ No newline at end of file
package lec10.glab.multi_core;
/**
* Created by ag on 11/30/2014.
*/
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
//http://www.journaldev.com/1090/java-callable-future-example
public class MyCallable implements Callable<String> {
@Override
public String call() throws Exception {
Thread.sleep(10);
//return the thread name executing this callable task
return Thread.currentThread().getName();
}
public static void main(String args[]){
int nNumProcessor = Runtime.getRuntime().availableProcessors();
System.out.println("number of available cores: " + nNumProcessor);
ExecutorService executor = Executors.newFixedThreadPool(nNumProcessor);
//create a list to hold the Future object associated with Callable
List<Future<String>> list = new ArrayList<Future<String>>();
//Create MyCallable instance
Callable<String> callable = new MyCallable();
for(int i=0; i< 100; i++){
//submit Callable tasks to be executed by thread pool
Future<String> future = executor.submit(callable);
//add Future to the list, we can get return value using Future
list.add(future);
}
for(Future<String> fut : list){
try {
//print the return value of Future, notice the output delay in console
// because Future.get() waits for task to get completed
System.out.println(new Date()+ "::"+fut.get());
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
}
//shut down the executor service now
executor.shutdown();
System.out.println("done");
}
}
\ No newline at end of file
......@@ -64,8 +64,12 @@ public class MockGame {
button = new JButton("fire");
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
new Thread(new Mp3(System.getProperty("user.dir") + "/src/edu/uchicago/cs/java/lec10/playsounds/snds/gun_plasmafire.mp3")).start();
System.out.println( System.getProperty("user.dir"));
new Thread(new Mp3(System.getProperty("user.dir") + "\\src\\lec10\\glab\\playsounds\\snds\\gun_plasmafire.mp3")).start();
}
});
......@@ -74,7 +78,7 @@ public class MockGame {
button_1 = new JButton("big explosion");
button_1.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
new Thread(new Mp3(System.getProperty("user.dir") + "/src/edu/uchicago/cs/java/lec10/playsounds/snds/explosion_enormous.mp3")).start();
new Thread(new Mp3(System.getProperty("user.dir") + "\\src\\lec10\\glab\\playsounds\\snds\\explosion_enormous.mp3")).start();
}
});
......@@ -89,7 +93,7 @@ public class MockGame {
// new Thread(new Mp3Loop(System.getProperty("user.dir")+ "/src/edu/uchicago/cs/java/lec10/playsounds/snds/loop5.mp3")).start();
new Thread(new Mp3Loop(System.getProperty("user.dir")+ "/src/edu/uchicago/cs/java/lec10/playsounds/snds/drums09.mp3")).start();
new Thread(new Mp3Loop(System.getProperty("user.dir")+ "\\src\\lec10\\glab\\playsounds\\snds\\drums09.mp3")).start();
}
......@@ -100,7 +104,7 @@ public class MockGame {
btnOld.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
new Thread(new ClipLoopOldSchool("file://" + System.getProperty("user.dir") + "/src/edu/uchicago/cs/java/lec10/playsounds/snds/samisen.au")).start();
new Thread(new ClipLoopOldSchool("file://" + System.getProperty("user.dir") + "\\src\\lec10\\glab\\playsounds\\snds\\samisen.au")).start();
}
});
frame.getContentPane().add(btnOld);
......
......@@ -11,7 +11,7 @@ public static void main(String args[]) {
//you need an au file to do it.
URL url = new URL(
"file://" + System.getProperty("user.dir") + "/src/edu/uchicago/cs/java/lec10/playsounds/snds/samisen.au");
"file://" + System.getProperty("user.dir") + "\\src\\lec10\\glab\\playsounds\\snds\\samisen.au");
AudioClip clip = Applet.newAudioClip(url);
clip.play();
......
......@@ -13,24 +13,17 @@ public class SafeDriver {
public static void main(String[] args) {
// ThreadSafeArrayList tsa = new ThreadSafeArrayList();
// Thread thr1 = new Thread(new SafeRunner(tsa));
// Thread thr2 = new Thread(new SafeRunner(tsa));
// Thread thr3 = new Thread(new SafeRunner(tsa));
//
// thr1.start();
// thr2.start();
// thr3.start();
//relatively more safe than regular arraylist.
CopyOnWriteArrayList<String> strVals = new CopyOnWriteArrayList<String>();
Thread thr1 = new Thread(new SafeRunnerEasy(strVals));
Thread thr2 = new Thread(new SafeRunnerEasy(strVals));
Thread thr3 = new Thread(new SafeRunnerEasy(strVals));
thr1.start();
thr2.start();
thr3.start();
}
......
......@@ -14,13 +14,13 @@ public class SafeRunnerEasy implements Runnable {
@Override
public void run() {
for (int nC = 0; nC < 1000; nC++) {
strVals.add((new Integer(nC)).toString());
System.out.println("adding " + (new Integer(nC)).toString() );
}
for (int nC = 0; nC < 1000; nC++) {
strVals.add((new Integer(nC)).toString());
System.out.println("adding " + (new Integer(nC)).toString());
}
}
......
......@@ -4,64 +4,59 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
//you can get a lock on an item by using the synchronized keyword.
//http://www.avajava.com/tutorials/lessons/how-do-i-synchronize-a-list-or-other-collection-in-java.html
public class SynchCollection {
private static List<Integer> intNums = Collections.synchronizedList(new ArrayList<Integer>());
public static void main(String[] args) {
//populate the ArrayList with anonymous thread
new Thread(new Runnable(){
public void run(){
synchronized (intNums) {
for (int nC = 0; nC < 1000; nC++) {
intNums.add(new Integer(nC));
System.out.println("adding " + nC);
}
}
}
}).start();
//remove any element that is divisisble by 3
new Thread(new Runnable(){
public void run(){
synchronized (intNums) {
for (int nC = 0; nC < 1000; nC++){
if(nC % 3 == 0){
intNums.remove(new Integer(nC));
System.out.println("try to remove " + nC);
}
}
}
}
}).start();
//print the elements
new Thread(new Runnable(){
public void run(){
synchronized (intNums) {
for (Integer intMe : intNums) {
System.out.println(intMe);
}
}
}
}).start();
}
private static List<Integer> intNums = Collections.synchronizedList(new ArrayList<Integer>());
public static void main(String[] args) {
//populate the ArrayList with anonymous thread
new Thread(new Runnable() {
public void run() {
synchronized (intNums) {
for (int nC = 0; nC < 1000; nC++) {
intNums.add(new Integer(nC));
System.out.println("adding " + nC);
}
}
}
}).start();
//remove any element
new Thread(new Runnable() {
public void run() {
synchronized (intNums) {
for (int nC = 0; nC < 1000; nC++) {
intNums.remove(new Integer(nC));
System.out.println("remove " + nC);
}
}
}
}).start();
//print the elements (if they exist)
new Thread(new Runnable() {
public void run() {
synchronized (intNums) {
for (Integer intMe : intNums) {
System.out.println("print " +intMe);
}
}
}
}).start();
}
}
\ No newline at end of file
......@@ -6,13 +6,13 @@ import java.util.ArrayList;
{
public static void main(String [] args)
{
ArrayList<String> strNames = null;
ArrayList<Student> stuNames = null;
try
{
FileInputStream fis =
new FileInputStream("strStudents.ser");
new FileInputStream("stuNames.ser");
ObjectInputStream ois = new ObjectInputStream(fis);
strNames = (ArrayList<String>) ois.readObject();
stuNames = (ArrayList<Student>) ois.readObject();
ois.close();
fis.close();
}catch(IOException e)
......@@ -26,8 +26,8 @@ import java.util.ArrayList;
return;
}
for (String str : strNames) {
System.out.println(str);
for (Student stu : stuNames) {
System.out.println(stu);
}
}
......
......@@ -10,21 +10,25 @@ public class SerializeDemo
public static void main(String [] args)
{
ArrayList<String> strNames = new ArrayList<String>();
strNames.add("Adam");
strNames.add("Ken");
strNames.add("Wei");
strNames.add("Gyan");
strNames.add("David");
ArrayList<Student> stuNames = new ArrayList<>();
stuNames.add(new Student("David",2014));
stuNames.add(new Student("Gyan",2014));
stuNames.add(new Student("Melissa",2014));
stuNames.add(new Student("Mathew",2014));
stuNames.add(new Student("Arjun",2014));
stuNames.add(new Student("Drew",2014));
String strCurrentDir = System.getProperty("user.dir");
try
{
FileOutputStream fos =
new FileOutputStream("strStudents.ser");
new FileOutputStream(strCurrentDir + "/stuNames.ser");
ObjectOutputStream oos =
new ObjectOutputStream(fos);
oos.writeObject(strNames);
oos.writeObject(stuNames);
oos.close(); //flushes and closes
fos.close();
}catch(IOException e)
......
package lec10.glab.serialize;
import java.io.Serializable;
/**
* Created with IntelliJ IDEA.
* User: ag
* Date: 11/28/13
* Time: 4:34 PM
* To change this template use File | Settings | File Templates.
*/
//needs to implement the serializeale interface
public class Student implements Serializable {
private String mName;
private int mYear;
public Student(String name, int year) {
mYear = year;
mName = name;
}
public String getName() {
return mName;
}
public void setName(String name) {
mName = name;
}
public int getYear() {
return mYear;
}
public void setYear(int year) {
mYear = year;
}
@Override
public String toString() {
return "Student{" +
"mName='" + mName + '\'' +
", mYear=" + mYear +
'}';
}
}
package lec10.glab.serialize_xml;
import java.io.Serializable;
/**
* Created with IntelliJ IDEA.
* User: ag
* Date: 11/28/13
* Time: 4:43 PM
* To change this template use File | Settings | File Templates.
*/
public class HighScore implements Serializable, Comparable<HighScore> {
private String mName;
private long mScore;
//you must include a no-arg consturctor
public HighScore() {
}
public HighScore(String name, String score) {
long lScore =0;
try {
lScore= Long.parseLong(score);
} catch (NumberFormatException e) {
// e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
}
mName = name;
mScore = lScore;
}
public String getName() {
return mName;
}
public void setName(String name) {
mName = name;
}
public long getScore() {
return mScore;
}
public void setScore(long score) {
mScore = score;
}
@Override
public String toString() {
return mName + " : "+ mScore;
}
@Override
public int compareTo(HighScore highScore) {
int nRet = 0;
//sort descending
if (this.getScore() > highScore.getScore()) {
nRet = -1;
} else if (this.getScore() < highScore.getScore()) {
nRet = 1;
}
return nRet;
}
@Override
public boolean equals(Object obj) {
if (((HighScore)obj).getName().equalsIgnoreCase(this.getName())){
return true;
} else {
return false;
}
}
}
package lec10.glab.serialize_xml;
import java.io.Serializable;
import java.util.ArrayList;
/**
* Created with IntelliJ IDEA.
* User: ag
* Date: 12/2/13
* Time: 10:56 AM
* To change this template use File | Settings | File Templates.
*/
public class HighScores extends ArrayList<HighScore> {
//make this ArrayList behave like a Set with regards to getName()
@Override
public boolean add(HighScore highScore) {
if (!contains(highScore)){
return super.add(highScore);
} else {
remove(highScore);
return super.add(highScore);
}
}
}
package lec10.glab.serialize_xml;
import java.beans.XMLDecoder;
import java.beans.XMLEncoder;
import java.io.*;
import java.util.*;
/**
* Created with IntelliJ IDEA.
* User: ag
* Date: 11/28/13
* Time: 4:53 PM
* To change this template use File | Settings | File Templates.
*/
//example found here: http://stackoverflow.com/questions/4602210/xmlencoder-in-java-for-serialization
public class SerialDriver {
private static final String FILENAME = "highscore.xml";
public static void main(String[] args) {
createFileIfNotExist(FILENAME);
Scanner scan = new Scanner(System.in);
String strUser, strName, strScore;
outer:
while (true) {
System.out.println("press a for add high-score, p for print high-scores descending, or x for print xml, or q to quit:");
strUser = scan.nextLine();
strUser = strUser.toLowerCase();
try {
switch (strUser) {
case "a":
System.out.println("What is your name?");
strName = scan.nextLine();
System.out.println("What is your score?");
strScore = scan.nextLine();
HighScores highScores = getHighScores();
highScores.add(new HighScore(strName, strScore));
writeHighScores(highScores);
break;
case "p":
HighScore[] highScoresArray = getSortedHighScores(getHighScores());
for (HighScore highScore : highScoresArray) {
System.out.println(highScore);
}
System.out.println();
break;
case "x":
printXml();
break;
case "q":
break outer;
default:
}
} catch (IOException e) {
System.out.println("There's been an error: " + e.getMessage());
continue outer;
}
}
System.out.println("Thanks for playing.");
}
private static void createFileIfNotExist(String strFileName) {
String strCurrentDir = System.getProperty("user.dir");
File highScoreFile = new File(strCurrentDir + "/" + strFileName);
if (!highScoreFile.exists()) {
try {
writeHighScores(new HighScores());
} catch (FileNotFoundException e) {
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
}
}
}
private static void writeHighScores(HighScores highScores) throws FileNotFoundException {
XMLEncoder encoder = new XMLEncoder(new BufferedOutputStream(
new FileOutputStream(FILENAME)));
encoder.writeObject(highScores);
encoder.close();
}
private static void printXml() throws IOException {
String strRet = "";
BufferedReader br = new BufferedReader(new FileReader(new File(FILENAME)));
String strLine = "";
while ((strLine = br.readLine()) != null) {
strRet += strLine + "\n";
}
System.out.println(strRet);
}
private static HighScores getHighScores() throws FileNotFoundException {
XMLDecoder decoder = new XMLDecoder(new FileInputStream(FILENAME));
HighScores listFromFile = null;
try {
listFromFile = (HighScores) decoder.readObject();
} catch (ArrayIndexOutOfBoundsException e) {
listFromFile = new HighScores();
} finally {
decoder.close();
}
return listFromFile;
}
private static HighScore[] getSortedHighScores(HighScores highScores) {
HighScore[] highScoresArray = highScores.toArray(new HighScore[highScores.size()]);
Arrays.sort(highScoresArray);
return highScoresArray;
}
}
......@@ -3,36 +3,37 @@ package lec10.glab.socket;
import java.net.*;
import java.io.*;
import java.util.Scanner;
//this is the client
public class GreetingClient
{
public static void main(String [] args)
{
String serverName = "localhost";
int port = 6066;
try
{
System.out.println("Connecting to " + serverName
+ " on port " + port);
Socket client = new Socket(serverName, port);
System.out.println("Just connected to "
+ client.getRemoteSocketAddress());
OutputStream outToServer = client.getOutputStream();
DataOutputStream out =
new DataOutputStream(outToServer);
public class GreetingClient {
public static void main(String[] args) {
String serverName = "localhost";
int port = 6061;
Scanner scan = new Scanner(System.in);
try {
System.out.println("Connecting to " + serverName + " on port " + port);
Socket client = new Socket(serverName, port);
while (true) {
OutputStream outToServer = client.getOutputStream();
DataOutputStream out = new DataOutputStream(outToServer);
System.out.println("Please send your command to the server, such as '35 in C' or '76 in F' or x to quit");
String strSendToServer = scan.nextLine();
out.writeUTF(strSendToServer);
InputStream inFromServer = client.getInputStream();
DataInputStream in = new DataInputStream(inFromServer);
String strReadFromServer = in.readUTF();
if (strReadFromServer.equalsIgnoreCase("exit"))
break;
else
System.out.println(strReadFromServer);
}
System.out.println("Client shutting down.");
client.close();
out.writeUTF("Hello from "
+ client.getLocalSocketAddress());
InputStream inFromServer = client.getInputStream();
DataInputStream in =
new DataInputStream(inFromServer);
System.out.println("Server says " + in.readUTF());
client.close();
}catch(IOException e)
{
e.printStackTrace();
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
\ No newline at end of file
......@@ -4,56 +4,105 @@ package lec10.glab.socket;
import java.net.*;
import java.io.*;
public class GreetingServer extends Thread
{
private ServerSocket serverSocket;
public GreetingServer(int port) throws IOException
{
serverSocket = new ServerSocket(port);
serverSocket.setSoTimeout(10000);
}
public void run()
{
while(true)
{
try
{
System.out.println("Waiting for client on port " +
serverSocket.getLocalPort() + "...");
Socket server = serverSocket.accept();
System.out.println("Just connected to "
+ server.getRemoteSocketAddress());
DataInputStream in =
new DataInputStream(server.getInputStream());
System.out.println(in.readUTF());
DataOutputStream out =
new DataOutputStream(server.getOutputStream());
out.writeUTF("Thank you for connecting to "
+ server.getLocalSocketAddress() + "\nGoodbye!");
server.close();
}catch(SocketTimeoutException s)
{
System.out.println("Socket timed out!");
break;
}catch(IOException e)
{
/*
A socket is an endpoint (combination server URL + port) for communication between two machines. The actual work of the socket is performed by an
instance of the SocketImpl class. An application, by changing the socket factory that creates the socket implementation,
can configure itself to create sockets appropriate to the local firewall.
*/
public class GreetingServer implements Runnable {
private ServerSocket serverSocket;
public GreetingServer(int port) throws IOException {
serverSocket = new ServerSocket(port);
}
public static void main(String[] args) {
int port = 6061;
try {
Thread thr = new Thread(new GreetingServer(port));
thr.start();
} catch (IOException e) {
e.printStackTrace();
break;
}
}
}
public static void main(String [] args)
{
int port = 6066;
try
{
Thread t = new GreetingServer(port);
t.start();
}catch(IOException e)
{
e.printStackTrace();
}
}
}
}
@Override
public void run() {
Socket server = null;
DataOutputStream out;
try {
server = serverSocket.accept();
System.out.println("Waiting for client on port " + serverSocket.getLocalPort() + "...");
System.out.println("Just connected to " + server.getRemoteSocketAddress());
} catch (IOException e) {
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
}
outer:
while (true) {
try {
String strDegree = "";
String strConvertTo = "";
String strResult = "";
DataInputStream in = new DataInputStream(server.getInputStream());
String strFromClient = in.readUTF();
String[] strSplits = strFromClient.split(" ");
if (strSplits.length != 3)
break outer;
for (int nC = 0; nC < strSplits.length; nC++) {
if (strSplits[nC].equalsIgnoreCase("x")) {
break outer;
}
//ignore the "in"
switch (nC) {
case 0:
strDegree = strSplits[nC];
break;
case 2:
strConvertTo = strSplits[nC];
break;
}
}
if (strConvertTo.equalsIgnoreCase("C")) {
strResult = toCel(strDegree);
} else {
strResult = toFar(strDegree);
}
System.out.println(strFromClient);
out = new DataOutputStream(server.getOutputStream());
out.writeUTF("The server says that the answer is " + strResult);
} catch (IOException e) {
e.printStackTrace();
break outer;
}
}
try {
out = new DataOutputStream(server.getOutputStream());
out.writeUTF("exit");
System.out.println("Server shutting down.");
server.close();
} catch (IOException e) {
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
}
}
private static String toCel(String strFar) {
double dFar = Double.parseDouble(strFar);
return String.valueOf((dFar - 32) * 5.0 / 9);
}
private static String toFar(String strCel) {
double dCel = Double.parseDouble(strCel);
return String.valueOf(dCel * 9 / 5.0 + 32);
}
}
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="lec10.glab.swing_worker.SWorker">
<grid id="27dc6" binding="mPanel" layout-manager="GridLayoutManager" row-count="2" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<xy x="20" y="20" width="500" height="400"/>
</constraints>
<properties/>
<border type="none"/>
<children>
<component id="db21a" class="javax.swing.JProgressBar" binding="mProgressBar">
<constraints>
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
</component>
<component id="ff007" class="javax.swing.JButton" binding="mGoButton" default-binding="true">
<constraints>
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text value="Done"/>
</properties>
</component>
</children>
</grid>
</form>
package lec10.glab.swing_worker;
import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.List;
import java.util.concurrent.ExecutionException;
/**
* Created with IntelliJ IDEA.
* User: ag
* Date: 12/2/13
* Time: 2:16 PM
* To change this template use File | Settings | File Templates.
*/
public class SWorker {
private JProgressBar mProgressBar;
private JButton mGoButton;
private JPanel mPanel;
public static void main(String[] args) {
JFrame frame = new JFrame("SWorker");
frame.setContentPane(new SWorker().mPanel);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
frame.setSize(500,200);
}
public SWorker() {
//do any intialization
//event listeners
mGoButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
mGoButton.setText("Running");
ProgressWorker progressWorker = new ProgressWorker();
progressWorker.execute();
}
});
}
/* @param <PARAM1> the result type returned by this {@code SwingWorker's}
* {@code doInBackground} and {@code get} methods
* @param <PARAM2> the type used for carrying out intermediate results by this
* {@code SwingWorker's} {@code publish} and {@code process} methods
*
* @since 1.6
*/
//the first generic parameter is the return value, the second is the intermediate chunked value
private class ProgressWorker extends SwingWorker<String, Integer> {
private int nC = 0;
//on background thread
@Override
protected String doInBackground() throws Exception {
while (nC <=100){
Thread.sleep((int)(Math.random() * 100));
publish(nC++);
}
return "Done";
}
//this is the feedback it gets while it's running - on UI Thread
@Override
protected void process(List<Integer> chunks) {
//all we need is the first value of the chunks
//this occurs because of time-slicing
mProgressBar.setValue(chunks.get(0));
}
//this is what happens when it's done - on UI Thread
@Override
protected void done() {
try {
mProgressBar.setValue(100);
mGoButton.setText(get());
} catch (InterruptedException e) {
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
} catch (ExecutionException e) {
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
}
}
}
}
package lec10.glab.synch;
public class BankAccountExampleSynchronizedDriver {
/**
* @param args
*/
public static void main(String[] args) {
BankAccount bnk = new BankAccount();
final double AMOUNT = 100.0;
final int REPS = 100;
final int THREADS = 100;
for (int nC = 0; nC < THREADS; nC++) {
new Thread(new Depositer(bnk, AMOUNT, REPS)).start();
new Thread(new Withdrawer(bnk, AMOUNT, REPS)).start();
}
}
}
class Depositer implements Runnable{
private static final int DELAY = 1;
private BankAccount bnk;
private double dAmount;
private int nCount;
public Depositer(BankAccount bnk, double dAmount, int nCount) {
super();
this.bnk = bnk;
this.dAmount = dAmount;
this.nCount = nCount;
}
public void run(){
try {
for (int nC = 0; nC < nCount; nC++) {
bnk.deposit(dAmount);
Thread.sleep(DELAY);
}
} catch (InterruptedException exp) {
// TODO Auto-generated catch block
exp.printStackTrace();
}
}
}
class BankAccount {
private double dBalance;
public BankAccount() {
this.dBalance = 0;
}
/*
Try removing the synchronized keyword from the signature of these methods and run the
BankAccountExampleSynchronizedDriver example to see what will happen.
*/
public synchronized void deposit(double dAmount){
System.out.print("Depositing " + dAmount);
double dNewBal = getBalance() + dAmount;
System.out.println(", the new balance is "+ dNewBal);
setBalance(dNewBal);
}
public synchronized void withdraw(double dAmount){
System.out.print("Withdrawing " + dAmount);
double dNewBal = getBalance() - dAmount;
System.out.println(", the new balance is "+ dNewBal);
setBalance(dNewBal);
}
public double getBalance() {
return this.dBalance;
}
public void setBalance(double dBalance) {
this.dBalance = dBalance;
}
}
class Withdrawer implements Runnable{
private static final int DELAY = 1;
private BankAccount bnk;
private double dAmount;
private int nCount;
public Withdrawer(BankAccount bnk, double dAmount, int nCount) {
super();
this.bnk = bnk;
this.dAmount = dAmount;
this.nCount = nCount;
}
public void run(){
try {
for (int nC = 0; nC < nCount; nC++) {
bnk.withdraw(dAmount);
Thread.sleep(DELAY);
}
} catch (InterruptedException exp) {
// TODO Auto-generated catch block
exp.printStackTrace();
}
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment